Sagen Sie voraus, wohin der Mann gehen wird


17

Ein Mann lebt in der nordwestlichen Ecke (0, 0)einer Stadt mit Höhe hund Breite w. Jeden Tag geht er von zu Hause zur Grenze (?, w)oder (h, ?). Im folgenden Beispiel geht der Mann bis (3, 3)heute.

(0, 0) +--+  +  +  . (0, 4)
          |         
       +  +--+--+  .
                |   
       +  +  +  +  .
                |   
(3, 0) .  .  .  .  . (3, 4)

Der Mann zeichnet an jedem Punkt etwas auf ( +im obigen Beispiel). Jedes Mal, wenn er einen Punkt erreicht, geht er nach Osten, wenn das Stück ist, 1und sonst nach Süden. Das Stück wird umgedreht, nachdem er gegangen ist. Beispielsweise:

Day 1: 1--0  1  1    Day 2: 0  1  1  1    Day 3: 1--1--1--1--  Day 4: 0  0  0  0  
          |                 |                                         |           
       0  1--0  0           0  0  1  0           1  0  1  0           1--0  1  0  
             |              |                                            |        
       1  0  1--0           1--0  0  1           0  1  0  1           0  1--0  1  
                |              |                                            |     
Destination: (3, 3)  Destination: (3, 1)  Destination: (0, 4)  Destination: (3, 2)

Berechnen Sie anhand der Größe der Stadt und der Daten des Mannes das Ziel des Mannes nach nTagen.

Eingang:

In der ersten Zeile stehen drei Ganzzahlen h, wund n.

In den folgenden hZeilen stehen wganze Zahlen für den Datensatz des Mannes.

h <= 1000, w <= 1000, n <= 1000000000

Ausgabe:

Zwei ganze Zahlen, die das Ziel des Mannes nach nTagen angeben .

Beispiel Input:

3 4 3
1 0 1 1
0 1 0 0
1 0 1 0

Beispielausgabe:

0 4

Beispielcode:

#include <iostream>
using namespace std;
bool d[1000][1000];
int main(){
    int h, w, n;
    cin >> h >> w >> n;
    for(int i = 0; i < h; i++)
        for(int j = 0; j < w; j++)
            cin >> d[i][j];
    int i, j;
    while(n--)
        for(i = 0, j = 0; i < h && j < w;){
            bool &b = d[i][j];
            d[i][j] ? j++ : i++;
            b = !b;
        }
    cout << i << " " << j << endl;
}

Wertung:

  • Die niedrigste Byteanzahl in UTF-8 gewinnt.
  • Wenn die Laufzeit Ihres Codes unabhängig ist n, reduzieren Sie Ihre Punktzahl um 50%.
    • Berechnen Sie nicht einfach die Ergebnisse aller 1000000000 Tage oder tun Sie etwas ähnlich Dummes, um diesen Bonus zu erhalten. Finde einen effizienten Algorithmus!

2 Dinge, die ich nicht verstehe. Bei der Ausgabe verwenden Sie manchmal den Index 0, wenn Sie dies nicht tun. Wie funktioniert das? Sollte es wie border + 1 sein? Zweitens ist die zweite Zeile mit Punkten. Wie meinen Sie das?
Teun Pronk

Tag 4 sollte 3,2 richtig ausgeben?
Teun Pronk

2
Wenn nmein Code , egal was passiert, die Ergebnisse aller 1000000000 Tage berechnet und dann das Ergebnis von ausgibt n, bekomme ich trotzdem den Bonus von -50%?
User12205

@ace jetzt sagst du es so, es macht Sinn, nicht wahr? Danke dafür: P
Teun Pronk

@TeunPronk Ja. Es ist meine Schuld.
Johnchen902

Antworten:


7

GolfScript, 52.5 (105 Zeichen mit 50% Bonus)

~](;(\((2$(1,*+\@/{]zip 0\{~@@+.2$!+2/\@+.2/\@[\1&]}%zip~@;}%\;[{.0=0=\1${{1>}%}{1>}if.{~}%}do;].1-,n@0-,

Die Version ist sehr effizient und kann auch für große Werte online getestet werden.

Es wird ein Ansatz verwendet, der der Lösung von user2357112 ähnelt .


1
Bitte frage nicht nach einer Erklärung ;-) Ich kann es nicht einmal ändern, ohne zu brechen und das Biest zu debuggen, ist schrecklich.
Howard

13

Python 2, 192 Bytes * 0,5 Bonus = 96

Um dieses Problem effizient zu lösen, können wir anhand der Häufigkeit, mit der die Zellen oben und links besucht werden, berechnen, wie oft jede Zelle besucht wird, ohne dass die genauen Pfade ermittelt werden müssen. Effektiv simulieren wir nTrips auf einmal und verfolgen, wie oft jede Zelle verwendet wird.

Wesentliche Verbesserung durch Push-basierten Ansatz, inspiriert von der Lösung von johnchen902 :

r=lambda:map(int,raw_input().split())
h,w,n=r()
v=[n]+w*[0]
x=y=0
for i in range(h):
 for j,b in enumerate(r()):
    if i-x==j-y==0:d=v[j]&1^b;x+=d;y+=1^d
    f=v[j]+b>>1;v[j]-=f;v[j+1]+=f
print x,y

Bisherige Pull-basierte Implementierung:

r=lambda i:map(int,raw_input().split())
h,w,n=r(0)
x=range(h)
g=map(r,x)
v=[w*[0]for i in x]
v[0][0]=n-1
for i in x:
 for j in range(w):v[i][j]+=(i and(v[i-1][j]+(1^g[i-1][j]))/2)+(j and(v[i][j-1]+g[i][j-1])/2)
i=j=0
while i<h and j<w:f=g[i][j]^v[i][j]&1;j+=f;i+=1^f
print i,j

Originale, ungolfierte Version:

h, w, n = map(int, raw_input().split())
grid = [map(int, raw_input().split()) for i in xrange(h)]

# Determine the number of times each cell was visited in the first n-1 trips
visits = [[0]*w for i in xrange(h)]
visits[0][0] = n-1
for i in xrange(h):
    for j in xrange(w):
        if i:
            # Count visits from above cell
            visits[i][j] += (visits[i-1][j] + (not grid[i-1][j])) // 2
        if j:
            # Count visits from left cell
            visits[i][j] += (visits[i][j-1] + grid[i][j-1]) // 2

# Flip the bits corresponding to each cell visited an odd number of times
for i in xrange(h):
    for j in xrange(w):
        grid[i][j] ^= visits[i][j] & 1

# Figure out where the final trip ends
i = j = 0
while i < h and j < w:
    if grid[i][j]:
        j += 1
    else:
        i += 1

print i, j

1
Sie können das not bis 1^und das lange kürzen , wenn die Bedingung geschrieben werden kann f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Howard

@ Howard: Danke. Bearbeitungen angewendet.
user2357112 unterstützt Monica

1
Wenn Sie erlauben , reinen Parameter zu nehmen ( r = lambda x: ...), dann können Sie verkürzen g=[r()for i in x]zu g=map(r,x).
Roberto Bonvallet

@RobertoBonvallet: Ja. Beratung umgesetzt.
user2357112 unterstützt Monica

8

Ruby, 159, 143

n,*l=$<.read.split$/
i=->a{a.split.map &:to_i}
x=y=l.map!{|k|i[k]}
(n=i[n])[-1].times{x=y=0
(x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}
p x,y

In der ersten Zeile wird der *Operator verwendet, um die erste Eingabezeile in einer Variablen und den Rest der Eingabe in einer anderen Variablen zu erfassen. Dann wird eine iwird Funktion zu konvertieren definiert "1 2 3 4"in [1, 2, 3, 4], die beide aufgetragen wird lund n. ( xund ywerden für später gespeichert.)

n[-1]Ist das letzte Element von n, so wird der folgende Block (die Simulation) so oft ausgeführt. Als erstes xund ywerden auf Null initialisiert (sie sind außerhalb des Blocks erklärt , so dass deren Umfang groß genug ist), und dann die Simulation Linie ausgeführt wird, das ist ziemlich selbsterklärend ist, aber hier ist einige Kommentar sowieso:

l[x][y]<1?            is it zero (less than one)?
x+=l[x][y]=1          if it's zero, set it to one, and (conveniently) we can add that to x
:y+=(l[x][y]=0)+1     otherwise, set it to zero, add one, and add that to y
 while x<n[0]&&y<n[1] keep doing this while we're still inside the array

Edit: Neue Simulationszeile von Howard, danke! Ich bin mir ziemlich sicher, dass ich verstehe, wie es funktioniert, aber ich habe keine Zeit, eine Erklärung hinzuzufügen, daher wird eine später hinzugefügt.

Schließlich p x,ygibt die Zahlen aus, und wir sind fertig!


Einige grundlegende Gewinne: Ändern Sie den Zeilenvorschub auf $/und die while-Schleife kann auf reduziert werden (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Howard

4

Delphi XE3 (437 Bytes || 897 874 ohne Bonus gezählt)

Als ich darüber nachdachte, wie ich das mit dem Bonus lösen könnte, dachte ich an Folgendes.
Wenn Sie 4 Tage laufen, wird die Zelle 0,0 4 Mal geändert. Die Zelle auf der rechten Seite wird zweimal geändert, ebenso die Zelle darunter.
Wenn es eine ungerade Anzahl von Tagen gibt und die Zahl in der Zelle mit 1 beginnt, erhält die Zelle rechts eine mehr als die Zelle darunter und umgekehrt, wenn die Zelle 0 ist.

Auf diese Weise können Sie für jede Zelle sehen, ob der Endwert geändert werden soll um: Zelle wurde X-mal geändert. wenn X mod 2> 0 ist, dann ändere die Zelle.

Ergibt folgenden Code:
{Whispers at JohnChen902} bekomme ich jetzt deine Zustimmung? : P

uses SysUtils,Classes,idglobal;var a:TArray<TArray<byte>>;b:TArray<TArray<int64>>;h,w,x,y,t:int16;n:int64;s:string;r:TStringList;tra:byte;begin r:=TStringList.Create;readln(h,w,n);h:=h-1;w:=w-1;for y:=0to h do begin readln(s);r.Add(StringReplace(s,' ','',[rfReplaceAll]));end;SetLength(a,h);SetLength(b,h);for y:=0to h do begin SetLength(a[y],w);SetLength(b[y],w);for x:=1to Length(r[y])do a[y][x-1]:=Ord(r[y][x])-48;end;b[0][0]:=n-1;for Y:=0to h do for X:=0to w do begin t:=b[y][x];if x<w then b[y][x+1]:=b[y][x+1]+iif((t mod 2=1)and(a[y][x]=1),(t div 2)+1,t div 2);if y<h then b[y+1][x]:=b[y+1][x]+iif((b[y][x]mod 2=1)and(a[y][x]=0),(t div 2)+1,t div 2);end;for Y:=0to h do for X:=0to w do if b[y][x]mod 2=1then a[y][x]:=iif(a[y][x]=1,0,1);y:=0;x:=0;repeat a[y][x]:=iif(a[y][x]=1,0,1);if a[y][x]=1then inc(y) else inc(x);until(y>h)or(x>w);write(Format('%d %d',[y,x]));end.

Ungolfed

uses
  SysUtils,Classes,idglobal;
var
  a:TArray<TArray<byte>>;
  b:TArray<TArray<int64>>;
  h,w,x,y,t:int16;
  n:int64;
  s:string;
  r:TStringList;
  tra:byte;
begin
  r:=TStringList.Create;
  readln(h,w,n);
  h:=h-1;w:=w-1;
  for y:=0to h do
  begin
    readln(s);
    r.Add(StringReplace(s,' ','',[rfReplaceAll]));
  end;
  SetLength(a,h);
  SetLength(b,h);
  for y:=0to h do
  begin
    SetLength(a[y],w);
    SetLength(b[y],w);
    for x:=1to Length(r[y])do
      a[y][x-1]:=Ord(r[y][x])-48;
  end;
  b[0][0]:=n-1;
  for Y:=0to h do
    for X:=0to w do
    begin
      t:=b[y][x];
      if x<w then
        b[y][x+1]:=b[y][x+1]+iif((t mod 2=1)and(a[y][x]=1),(t div 2)+1,t div 2);
      if y<h then
        b[y+1][x]:=b[y+1][x]+iif((b[y][x]mod 2=1)and(a[y][x]=0),(t div 2)+1,t div 2);
    end;
  for Y:=0to h do
    for X:=0to w do
      if b[y][x]mod 2=1then
        a[y][x]:=iif(a[y][x]=1,0,1);
  y:=0;x:=0;
  repeat
    a[y][x]:=iif(a[y][x]=1,0,1);
    if a[y][x]=1then
      inc(y)
    else
      inc(x);
  until(y>h)or(x>w);
  write(Format('%d %d',[y,x]));
end.

Du hast meine Stimme noch nicht bekommen. Ich habe zu Abend gegessen. (Upvoted)
johnchen902

4

C ++ 213 Bytes * 0,5 = 106,5

Hier ist meine Lösung. Es ähnelt der Lösung von user2357112 , es gibt jedoch mehrere Unterschiede:

  • Zuerst schicke ich die Besuchszeiten nach rechts und unten, anstatt sie von oben und links zu berechnen.
  • Zweitens mache ich alles (Eingabe lesen, Versand, Ort des Mannes verfolgen) gleichzeitig.
  • Drittens behalte ich nur eine Speicherzeile.
#include <iostream>
int o[1001],h,w,r,c,i,j,t,u;int main(){std::cin>>h>>w>>*o;for(;i<h;i++)for(j=0;j<w;)std::cin>>t,u=o[j],o[j]/=2,u%2&&o[j+t]++,r-i|c-j||((u+t)%2?r:c)++,o[++j]+=u/2;std::cout<<r<<" "<<c<<"\n";}

Hier ist die ungolfed Version:

#include <iostream>
using namespace std;
int o[1001];
int main(){
    int h, w, n;
    cin >> h >> w >> n;
    o[0] = n;
    int r = 0, c = 0;
    for(int i = 0; i < h; i++)
        for(int j = 0; j < w; j++){
            bool t;
            cin >> t;
            int u = o[j];
            o[j + 1] += u / 2;
            o[j] = u / 2;
            if(u % 2)
                (t ? o[j + 1] : o[j])++;
            if(r == i && c == j)
                ((u + t) % 2 ? r : c)++;
        }
    cout << r << " " << c << endl;
}

Diese drei Unterschiede machen die Dinge viel enger. Wir können die Indizierung verkürzen und mehrere redundante Datenstrukturen kombinieren. Die Logik zum Verschieben von Besuchen nach vorne ist wesentlich kürzer als die Logik zum Verschieben von Besuchen aus vorherigen Zellen. Horizontale Randbedingungen werden einfach dadurch behandelt, dass die Datenstruktur um einen zusätzlichen Platz nach rechts erweitert wird, und vertikale Randbedingungen sind kein Problem.
user2357112 unterstützt Monica

Ich habe Ihre Antwort positiv bewertet und die Konzepte in meinen eigenen Code integriert. Bisher haben sie 84 Bytes aus meiner Lösung entfernt, was einer Verbesserung von 30% entspricht.
user2357112 unterstützt Monica

Ich vermute, Sie könnten in der Lage sein, einige Bytes zu sparen, indem Sie nicht tun --*o;und stattdessen wechseln, in welchem ​​Fall Sie den Kerl nach unten und in welchem ​​Fall Sie den Kerl nach rechts bewegen.
user2357112 unterstützt Monica

@ user2357112 Implementiert, aber die Codelänge hat sich aufgrund eines vorherigen Fehlers erhöht (es sollten 218 Byte gewesen sein).
Johnchen902

3

Python, 177 Bytes

Mein erster Versuch in Code Golfing, also tut mir leid, wenn ich hier etwas falsch gemacht habe! Code, mit dem die Eingabe basierend auf dem Code von user2357112 erfasst wird.

l=lambda:map(int,raw_input().split())
h,w,n=l()
m=[l() for i in[1]*h]
while n>0:
 n-=1;x=y=0
 while x!=w and y!=h:
  if m[y][x]>0:m[y][x]=0;x+=1
  else:m[y][x]=1;y+=1
print y,x

Eingang:

3 4 3
1 0 1 1
0 1 0 0
1 0 1 0

Ausgabe:

0 4

2

R, 196 Bytes * 0,5 = 98

f=function(h,w,n,x){I=J=rep(1,n);for(i in 1:h)for(j in 1:w){M=which(I==i&J==j);N=length(M);if(N){z=seq(1,N,by=2);if(x[i,j])z=-z;f=M[-z];s=M[z];I[f]=i;J[f]=j+1;I[s]=i+1;J[s]=j}};cat(I[n]-1,J[n]-1)}

Ungolfed:

f=function(h,w,n,x) {
  I = J = rep(1,n)

  for(i in 1:h) for(j in 1:w) {
    M = which(I==i&J==j)
    N = length(M)
    if (N) {
      z = seq(1,N,by=2)
      if (x[i,j]) z = -z
      f = M[-z]
      s = M[z]
      I[f] = i
      J[f] = j+1
      I[s] = i+1
      J[s] = j
    }
  }
  cat(I[n]-1, J[n]-1)
}

Verwendung:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
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.