1P5: Erdbeben!


13

USGS-Seismometer haben gerade ein schweres Erdbeben festgestellt! Notfallteams benötigen eine schnelle Schätzung der Anzahl der betroffenen Personen. Schreiben Sie ein Programm, um diese Schätzung zu berechnen.

Ihr Programm erhält 2 Eingaben. Das erste sind die Details des Erdbebens. Das Erdbeben wurde als ein Liniensegment modelliert, entlang dessen die Erde zerbrach, zusammen mit der kritischen Entfernung von der Verwerfung, innerhalb derer ein Schaden zu erwarten war. Die zweite Eingabe ist eine Liste des Standorts und der Bevölkerung der Städte in der Region. Ihr Programm sollte die Anzahl der in dem betroffenen Gebiet lebenden Personen berechnen, dh die Summe der Bevölkerung aller Städte innerhalb der kritischen Entfernung des Fehlersegments.

Eingang

Zuerst eine Linie, die das Erdbeben beschreibt und die x-, y-Koordinaten des Start- und Endpunkts des Fehlers sowie die kritische Entfernung enthält. Das Format ist A_x A_y B_x B_y D. Beispielsweise:

3.0 3.0 7.0 4.0 2.5

codiert den Fehler von (3.0.3.0) bis (7.0.4.0) und einen kritischen Abstand von 2,5.

Zweitens eine Zeile pro Stadt in dem Gebiet, die die x, y-Koordinaten der Stadt und ihrer Bevölkerung enthält. Beispielsweise:

1.0 1.0 2500
5.0 7.0 8000
3.0 4.0 7500
9.0 6.0 3000
4.0 2.0 1000

Bildbeschreibung hier eingeben

Ausgabe

Die Anzahl der Personen, die in dem betroffenen Gebiet leben. Für das obige Beispiel befinden sich nur die dritte und fünfte Stadt im Gefahrenbereich, die Ausgabe wäre also

8500

Kürzester Code gewinnt.

Beispiel 2

0.0 0.0 10.0 0.0 5.0
5.0 4.0 10000
5.0 -4.0 1000
5.0 6.0 100
11.0 2.0 10 
-4.0 4.0 1

erzeugt

11010

Muss die Ausgabe eine Ganzzahl sein, oder wäre 8500.0das für das Beispiel in Ordnung? Und könnten wir vielleicht noch mehr Testfälle bekommen?
Ventero

Was ist der Typ der Eingabe? Wie viele Nachkommastellen könnte es haben? Dies ist relevant für Sprachen ohne Gleitkomma.
Peter Taylor

Die Ausgabe muss eine Ganzzahl sein und darf keine gebrochenen Personen enthalten. Angenommen, die Eingabe beträgt höchstens 2 Dezimalstellen.
Keith Randall

Verlängert sich der kritische Bereich in einem Halbkreis um die Endpunkte oder handelt es sich nur um ein Rechteck?
Peter Olson

@ Peter: Es endet in Halbkreisen, also ist das Ganze rautenförmig.
Keith Randall

Antworten:


11

Ruby, 171 152 155 153

u,v,a,b,d=gets.split.map &:to_f
a-=u;b-=v
p eval$<.map{|l|"(x=%f-u;t=(a*x+b*y=%f-v)/(a*a+b*b);d*d<(x-a*t=t<0?0:t>1?1:t)**2+(y-t*b)**2?0:%d)"%l.split}*'+'

Dies ist meine erste Ruby-Einsendung und mein erstes Code-Golf überhaupt. Einfache Umsetzung der Aufgabe. Bitte geben Sie mir einige Hinweise zur Verbesserung (es muss einen kürzeren Weg zum Lesen von Floats geben ...).


Sie können einige Zeichen speichern, indem Sie die Klammern um mapund evalund das Inlining entfernen t. Und da Sie bereits evaluieren, können Sie anstelle von Format-Strings verwenden .to_f, sodass der letzte Block aufp eval$<.map{|l|"(x=%f-u;t=(x*a+b*y=%f-v)/(a**2+b**2);d*d<(x-t=t<0?0:t>1?1:t)**2+(y-t*b)**2?0:%d)"%l.split}*'+'
Ventero

@Ventero danke. Durch terneutes Inlining werden zwei weitere gespart.
Howard

Ich kann nicht erreichen, dass dies in Beispiel 2 (soeben hinzugefügt) funktioniert. Es treten Fehler mitundefined method > for nil:NilClass (NoMethodError)
Keith Randall,

@Keith sollte nun auch an Ihren Eingaben arbeiten.
Howard

4

Javascript (437)

Damit kann man wahrscheinlich deutlich Golf spielen, aber nicht genug, um die Ruby-Lösung zu übertreffen.

p=$("#i").text().split("\n");for(i=0;i<p.length;i++){p[i]=p[i].split(" ")}
z=p[0];a=z[0];b=z[1];c=z[2];d=z[3];e=z[4];o=0;f=[a,b];g=[c,d];
function q(r,s){return Math.sqrt(Math.pow(s[0]-r[0],2)+Math.pow(s[1]-r[1],2))}
for(i=1;i<p.length;i++){w=p[i];u=((w[0]-a)*(c-a)+(w[1]-b)*(d-b))/Math.pow(q(f,g,2),2);
x=[(a*1)+u*(c-a),(b*1)+u*(d-b)];l=e;m=w[2]*1;u=w[0];w=w[1];v=[u,w];
o+=q(v,x)<l&&q(x,g)+q(x,f)==q(f,g)?m:q(v,f)<l?m:q(v,g)<l?m:0}alert(o);

Sie können es hier in Aktion sehen .


2
Sie können 2 Zeichen speichern, indem Sie b-0anstelle von (b*1)1 Zeichen das abschließende Semikolon entfernen. Beginnen Sie schließlich mit M=Mathund ersetzen Sie alle Maths durch M, wobei Sie 6 Zeichen speichern. Mit Prototype und .valuespeichert 2 Zeichen (die #und eine Klammer).
Ry

4

C # - 743 715

namespace System{using Linq;using m=Math;class P{public float X,Y;}class E{static void Main(){Func<string,float>p=s=>float.Parse(s);Func<P,P,double>d=(a,b)=>{return a.X*b.X+a.Y*b.Y;},c=(a,b)=>{return a.X*b.Y-a.Y*b.X;};Func<P,P,P>u=(a,b)=>{return new P{X=a.X-b.X,Y=a.Y-b.Y};};Func<P,P,P,double>g=(A,B,C)=>{return d(u(C,B),u(B,A))>0?m.Sqrt(d(u(B,C),u(B,C))):d(u(C,A),u(A,B))>0?m.Sqrt(d(u(A,C),u(A,C))):m.Abs(c(u(B,A),u(C,A))/m.Sqrt(d(u(B,A),u(B,A))));};var n=IO.File.ReadAllLines("i");var i=n[0].Split();var q=new{A=new P{X=p(i[0]),Y=p(i[1])},B=new P{X=p(i[2]),Y=p(i[3])},D=p(i[4])};Console.WriteLine((from l in n.Skip(1)let f=l.Split()let w=new P{X=p(f[0]),Y=p(f[1])}where g(q.A,q.B,w)<q.D select p(f[2])).Sum());}}}

Nicht Golfspieler:

namespace System
{
    using Linq;
    using m = Math;
    class Point { public float X, Y;}
    class Earthquake
    {
        static void Main()
        {
            Func<string, float> parse = s => float.Parse(s);
            Func<Point, Point, double> dotProduct = (a, b) => { return a.X * b.X + a.Y * b.Y; }, 
                                       crossProduct = (a, b) => { return a.X * b.Y - a.Y * b.X; };
            Func<Point, Point, Point> subtract = (a, b) => { return new Point { X = a.X - b.X, Y = a.Y - b.Y }; };
            Func<Point, Point, Point, double> getDistance = (A, B, C) => { 
                return dotProduct(subtract(C, B), subtract(B, A)) > 0 ? 
                        m.Sqrt(dotProduct(subtract(B, C), subtract(B, C))) : 
                        dotProduct(subtract(C, A), subtract(A, B)) > 0 ? 
                            m.Sqrt(dotProduct(subtract(A, C), subtract(A, C))) : 
                            m.Abs(crossProduct(subtract(B, A), subtract(C, A)) / m.Sqrt(dotProduct(subtract(B, A), subtract(B, A)))); 
            };
            var inputLines = IO.File.ReadAllLines("i"); 
            var quakeLine = inputLines[0].Split(); 
            var quake = new { 
                PointA = new Point { X = parse(quakeLine[0]), Y = parse(quakeLine[1]) }, 
                PointB = new Point { X = parse(quakeLine[2]), Y = parse(quakeLine[3]) }, 
                Distance = parse(quakeLine[4]) 
            };
            var affectedPopulations = (from line in inputLines.Skip(1) 
                                       let fields = line.Split() 
                                       let location = new Point { X = parse(fields[0]), Y = parse(fields[1]) } 
                                       let population = parse(fields[2])
                                       where getDistance(quake.PointA, quake.PointB, location) < quake.Distance 
                                       select population);
            Console.WriteLine(affectedPopulations.Sum());
        }
    }
}

Irgendetwas stimmt nicht mit der Golfversion, ich erhalte eine Fehlermeldung, wenn ich sie kompiliere ( quake.cs(1,254): error CS1525: Unexpected symbol ',', expecting 'from', 'group', 'join', 'let', 'orderby', 'select', or 'where'). Die ungolfed Version funktioniert gut.
Keith Randall

@KeithRandall, hoppla - zu viel Golf!
Rebecca Chernoff

2

c - 471 Zeichen

#include <stdio.h>
#define F float
#define G getline(&v,&l,stdin)
F a[2],b[2],c[2],d[2],e[2],r,t,y,z;char*v;size_t l,n,p;
F s(F u[2],F v[2]){y=u[0]-v[0];z=u[1]-v[1];return y*y+z*z;}
j(F g[2],F h[2],F i[2]){*i=*g-*h;i[1]=g[1]-h[1];}
int i(){j(b,a,d);j(c,a,e);t=*d**e+d[1]*e[1];
return s(a,c)<=r||s(b,c)<=r||t>0&&t/s(a,b)<=1&&s(a,c)-t*t/s(a,b)<=r;}
int main(){G;sscanf(v,"%f %f %f %f %f",a,a+1,b,b+1,&r);r*=r;
while(G!=-1)sscanf(v,"%f %f %i",c,c+1,&p),n+=p*i();printf("%d\n",n);}

Es wird davon ausgegangen, dass Ihre Standardbibliothek hat getline.

Die Methode wird im Kommentar zur ungolfed version ein wenig erklärt:

#include <stdio.h>

float a[2],b[2],c[2],d[2],e[2],r,t,y,z;
char*v;
size_t l,n,p;
float s(float u[2],float v[2]){ /* returns the square of the distance
                   between two points */
  y=u[0]-v[0];
  z=u[1]-v[1];
  return y*y+z*z;
}
j(float g[2],float h[2],float i[2]){ /* sets i=g-h */
  i[0]=g[0]-h[0];
  i[1]=g[1]-h[1];
}
int i/*sCLose*/(){
  j(b,a,d); /* d=b-a */
  j(c,a,e); /* e=c-a */
  t=d[0]*e[0]+d[1]*e[1]; /* dot product */ 
  return 
    (s(a,c)<=r) || /* near one end point */
    (s(b,c)<=r) || /* near the other */
    (  
     (t>0) && /* C lies more "towards" B than away */
     (t/s(a,b)<=1) && /* Nearest point on AB to C lies between A and B */
     (s(a,c)-t*t/s(a,b)<=r) /* length of the altitude less than R */
       ); 
}
int main(){
  getline(&v,&l,stdin);
  sscanf(v,"%f %f %f %f %f",a,a+1,b,b+1,&r);
  r*=r; /* r is now r squared, as that is the only way we use it */
  printf("(%f, %f); (%f, %f): %f\n",a[0],a[1],b[0],b[1],r);
  while (getline(&v,&l,stdin) != -1){
    sscanf(v,"%f %f %i",c,c+1,&p);
    printf("\t (%f, %f): %d\n",c[0],c[1],p);
    n+=p*i/*sClose*/();
  }
  printf("%d\n",n);
}

0

Scala: 660 Zeichen:

object E extends App{
type I=Int
type D=Double
def b(h:D,i:D,x:I,y:I,d:D)=(x-h)*(x-h)+(y-i)*(y-i)<=d*d
def a(p:java.awt.Polygon,x:I,y:I,h:I,i:I,d:D,r:Array[String])={
val w=r(0).toDouble
val j=r(1).toDouble
val n=r(2).toInt
if (p.contains(w,j)||b(j,w,x,y,d)||b(j,w,i,h,d))n
else 0}
val s=new java.util.Scanner(System.in)
val b=s.nextLine.split(" ")
val c=b.map(_.toDouble)
val e=c.map(_.toInt)
val(x,h,y,i,d)=(e(0),e(2),e(1),e(3),c(4))
val f=List(x,h)
val g=List(y,i)
val p=new java.awt.Polygon((f:::f.reverse).toArray,(g.map(_-e(4)):::g.reverse.map(_+e(4))).toArray,4)
var r=0
while(s.hasNext){
val row=s.nextLine
r+=a(p,x,y,h,i,d,row.split(" "))}
println(r)}

ungolfed:

object Earthquake extends App {

  def bowContains (h: Double, i: Double, x:Int, y:Int, d: Double) : Boolean = {
    (x-h)*(x-h) + (y-i)*(y-i) <= d*d
  }

  import java.awt._    

  def affected (polygon: Polygon, x:Int, y:Int, h: Int, i: Int, d: Double, row: Array[String]) : Int = {
    val w = row (0).toDouble 
    val j = row (1).toDouble 
    val population = row (2).toInt
    if (polygon.contains (w, j) || bowContains (j, w, x, y, d) || bowContains (j, w, i, h, d))
      population 
    else 0 
  }
  val sc = new java.util.Scanner (System.in)
  val line = sc.nextLine.split (" ")

  val li = line.map (_.toDouble)
  val ll = li.map (_.toInt)

  val (x, h, y, i, d) = (ll (0), ll (2), ll (1), ll (3), li(4))
  val xs = List (x, h)
  val ys = List (y, i)

  val polygon = new Polygon ((xs ::: xs.reverse).toArray, (ys.map (_ - ll(4)) ::: ys.reverse.map (_ + ll(4))).toArray, 4)
  var res = 0 
  while (sc.hasNext) {
    val row = sc.nextLine
    println ("line: " + line) 
    res += affected (polygon, x, y, h, i, d, row.split (" "))     
  } 
  println (res)
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.