Prevedi dove andrà l'uomo


17

Un uomo vive nell'angolo nord-ovest (0, 0)di una città con altezza he larghezza w. Ogni giorno cammina da casa sua al confine (?, w)o (h, ?). Nel seguente esempio, l'uomo va a (3, 3)oggi.

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

L'uomo registra un po 'in ogni punto ( +nell'esempio sopra). Ogni volta che raggiunge un punto, va verso est se la punta è 1e verso sud altrimenti. Il pezzo viene girato dopo che se ne è andato. Per esempio:

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)

Date le dimensioni della città e il record dell'uomo, calcola la destinazione dell'uomo dopo ngiorni.

Ingresso:

Nella prima riga sono tre numeri interi h, we n.

Nelle hrighe seguenti sono wnumeri interi, che indicano il record dell'uomo.

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

Produzione:

Due numeri interi, che indicano la destinazione dell'uomo dopo n giorni.

Input di esempio:

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

Uscita campione:

0 4

Codice d'esempio:

#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;
}

punteggio:

  • Vince il conteggio dei byte più basso in UTF-8.
  • Se il tempo di esecuzione del tuo codice è indipendente n, riduci il punteggio del 50%.
    • Non solo calcolare i risultati di tutti i 1000000000 giorni o fare qualcosa di altrettanto stupido per ottenere questo bonus. Trova un algoritmo efficiente!

2 cose che non capisco. L'output, a volte usi l'indice 0 altre volte che non lo fai. Come funziona? Dovrebbe essere come border + 1? La seconda cosa è la seconda riga con punteggio. Che cosa intendi con questo?
Teun Pronk,

Il giorno 4 dovrebbe produrre 3,2 giusto?
Teun Pronk,

2
Se, indipendentemente da ciò che nè, il mio codice calcola i risultati di tutti i 1000000000 giorni, quindi genera il risultato di n, ricevo ancora il bonus del -50%?
user12205

@ace ora lo metti così, ha senso no? Grazie per quello: P
Teun Pronk

@TeunPronk Sì. È colpa mia.
johnchen902,

Risposte:


7

GolfScript, 52.5 (105 caratteri con bonus del 50%)

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

La versione è molto efficiente e può essere testata online anche per valori elevati.

Utilizza un approccio simile alla soluzione di user2357112 .


1
Per favore, non chiedere una spiegazione ;-) Non posso nemmeno cambiarlo senza rompere e il debug di questa bestia è orribile.
Howard,

13

Python 2, 192 byte * 0,5 bonus = 96

Per risolvere questo problema in modo efficiente, la realizzazione chiave è che possiamo calcolare quante volte ogni cella viene visitata in base al numero di volte in cui le celle sopra e a sinistra vengono visitate, senza bisogno di determinare i percorsi esatti presi. In effetti, simuliamon viaggi contemporaneamente e teniamo traccia di quante volte viene utilizzata ogni cella.

Miglioramento sostanziale grazie all'approccio push-based ispirato alla soluzione di 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

Implementazione precedente basata su pull:

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

Versione originale, non golfata:

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
È possibile ridurre il not per 1^e il lungo se la condizione può essere scritto f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Howard,

@Howard: grazie. Modifiche applicate.
user2357112 supporta Monica

1
Se si consente rdi prendere un parametro ( r = lambda x: ...), allora si può ridurre g=[r()for i in x]a g=map(r,x).
Roberto Bonvallet,

@RobertoBonvallet: Sì. Consulenza implementata.
user2357112 supporta 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

La prima riga utilizza l' *operatore per afferrare la prima riga di input in una variabile e il resto dell'input in un'altra. Quindi iviene definita una funzione da convertire "1 2 3 4"in [1, 2, 3, 4], che viene applicata a entrambi le n. ( xe yvengono salvati per dopo.)

n[-1]è l'ultimo elemento di n, quindi il seguente blocco (la simulazione) viene eseguito più volte. In primo luogo, xe yvengono inizializzati a zero (sono dichiarate al di fuori del blocco in modo che la loro portata è abbastanza grande), e quindi viene eseguita la linea di simulazione, che è abbastanza auto-esplicativo, ma ecco alcuni commenti in ogni caso:

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

Modifica: nuova linea di simulazione fornita da Howard, grazie! Sono abbastanza sicuro di capire come funziona ma non ho tempo di aggiungere una spiegazione, quindi ne verrà aggiunta una in seguito.

Infine, p x,ygenera i numeri e il gioco è fatto!


Alcune vittorie di base: cambia la nuova riga in $/e il ciclo while può essere ridotto a (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Howard,

4

Delphi XE3 (437 byte || 897 874 senza bonus conteggiato)

Quando ho pensato a come risolverlo con il bonus ho pensato a quanto segue.
Se cammini per 4 giorni, la cella 0,0 viene cambiata 4 volte. La cella alla sua destra viene cambiata due volte rispetto alla cella sottostante.
Se il numero di giorni è irregolare e il numero nella cella inizia con 1, la cella a destra ne ottiene uno in più rispetto alla cella sottostante e viceversa se la cella è 0.

In questo modo per ogni cella puoi vedere se il valore finale deve essere modificato da: La cella è stata cambiata X volte. se X mod 2> 0 allora cambia la cella.

Risultati nel seguente codice:
{Whispers at JohnChen902} ottengo il tuo voto adesso? : 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.

Non hai ancora ottenuto il mio voto. Stavo cenando. (Aggiornato)
johnchen902

4

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

Ecco la mia soluzione È simile alla soluzione di user2357112 , ma ci sono diverse differenze:

  • Innanzitutto, invio i tempi di visita a destra e in basso, invece di calcolarli dall'alto e da sinistra.
  • In secondo luogo, faccio tutto (leggere input, inviare, tracciare la posizione dell'uomo) contemporaneamente.
  • Terzo, tengo solo una riga di memoria.
#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";}

Ecco la versione ungolfed:

#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;
}

Queste tre differenze rendono le cose molto più difficili. Possiamo abbreviare l'indicizzazione e combinare diverse strutture di dati ridondanti. La logica per far avanzare le visite risulta essere molto più breve della logica per trascinare le visite dalle celle precedenti. Le condizioni al contorno orizzontali vengono gestite semplicemente estendendo la struttura dei dati di uno spazio aggiuntivo a destra e le condizioni al contorno verticali non rappresentano un problema.
user2357112 supporta Monica

Ho votato a fondo la tua risposta e ho incorporato i concetti nel mio codice. Finora hanno eliminato 84 byte dalla mia soluzione, con un miglioramento del 30%.
user2357112 supporta Monica

Sospetto che potresti essere in grado di salvare alcuni byte non facendo --*o;, e invece cambiando il caso in cui si sposta il ragazzo verso il basso e in quale caso si sposta il ragazzo a destra.
user2357112 supporta Monica

@utente2357112 Implementato, ma la lunghezza del codice aumenta a causa di un errore precedente (avrebbe dovuto essere di 218 byte).
johnchen902,

3

Python, 177 byte

Il mio primo tentativo in assoluto nel Code Golf, quindi mi dispiace se ho sbagliato qualcosa qui! Codice utilizzato per afferrare l'input in base al codice dell'utente2357112.

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

Ingresso:

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

Produzione:

0 4

2

R, 196 byte * 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)
}

Uso:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.