Prever para onde o homem irá

17

Um homem vive no canto noroeste (0, 0)de uma cidade com altura he largura w. Todos os dias ele sai de sua casa até a fronteira (?, w)ou (h, ?). No exemplo a seguir, o homem vai para (3, 3)hoje.

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

O homem registra um pouco em cada ponto ( +no exemplo acima). Toda vez que ele chega a um ponto, ele vai para o leste se a parte estiver 1e para o sul, caso contrário. O bit é invertido depois que ele sai. Por exemplo:

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)

Dado o tamanho da cidade e o histórico do homem, calcule o destino do homem depois de ndias.

Entrada:

Na primeira linha são três inteiros, h, we n.

Nas hlinhas a seguir estão wnúmeros inteiros, denotando o registro do homem.

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

Resultado:

Dois inteiros, indicando o destino do homem depois de ndias.

Entrada de amostra:

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

Saída de amostra:

0 4

Código de amostra:

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

Pontuação:

  • Menor contagem de bytes em vitórias UTF-8.
  • Se o tempo de execução do seu código for independente n, reduza sua pontuação em 50%.
    • Não basta calcular os resultados de todos os 1000000000 dias ou fazer qualquer coisa estúpida para obter esse bônus. Encontre um algoritmo eficiente!
johnchen902
fonte
2 coisas que eu não entendo. A saída, às vezes você usa o índice 0, outras vezes não. Como isso funciona? Deve ser como borda + 1? A segunda coisa é a segunda linha com pontuação. O que voce quer dizer?
Teun Pronk
O dia 4 deve produzir 3,2, certo?
228156 Tek Pronk
2
Se, não importa o que nseja, meu código calcula os resultados de todos os 1000000000 dias e depois gera o resultado de n, ainda recebo o bônus de -50%?
precisa saber é o seguinte
@ace agora você coloca assim, faz sentido, não é? Obrigado por isso: P
Teun Pronk 04/04
@TeunPronk Sim. É minha culpa.
precisa saber é o seguinte

Respostas:

7

GolfScript, 52,5 (105 caracteres com bônus de 50%)

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

A versão é muito eficiente e pode ser testada on-line, mesmo para grandes valores.

Ele usa uma abordagem semelhante à solução do user2357112 .

Howard
fonte
11
Por favor, não peça uma explicação ;-) Eu não posso nem mudar isso sem quebrar e depurar esta fera é horrível.
Howard
13

Python 2, 192 bytes * 0,5 de bônus = 96

Para resolver esse problema com eficiência, a principal conclusão é que podemos calcular quantas vezes cada célula é visitada com base no número de vezes que as células acima e à esquerda são visitadas, sem precisar determinar os caminhos exatos. Efetivamente, simulamos nviagens de uma só vez e acompanhamos quantas vezes cada célula é usada.

Melhoria substancial devido à abordagem baseada em push, inspirada na solução de 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

Implementação anterior, baseada em 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

Versão original e não destruída:

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
user2357112 suporta Monica
fonte
11
Você pode encurtar o not que 1^eo tempo se condição pode ser escrito f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Howard
@ Howard: Obrigado. Edições aplicadas.
User2357112 suporta Monica
11
Se você permitir r usar um parâmetro ( r = lambda x: ...), poderá abreviá-lo g=[r()for i in x]para g=map(r,x).
Roberto Bonvallet 04/04
@RobertoBonvallet: Sim. Assessoria implementada.
User2357112 suporta 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

A primeira linha usa o *operador para capturar a primeira linha de entrada em uma variável e o restante da entrada em outra. Em seguida, uma ifunção é definida para converter "1 2 3 4"em [1, 2, 3, 4], que é aplicada a ambos le n. ( xe ysão salvos para mais tarde.)

n[-1]é o último elemento de n, portanto, o seguinte bloco (a simulação) é executado tantas vezes. Primeiro, xe ysão inicializados com zero (eles são declarados fora do bloco para que seu escopo seja grande o suficiente) e, em seguida, a linha de simulação é executada, o que é bastante autoexplicativo, mas aqui estão alguns comentários:

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: nova linha de simulação fornecida por Howard, obrigado! Tenho certeza de que entendo como funciona, mas não tenho tempo para adicionar uma explicação; portanto, uma será adicionada mais tarde.

Finalmente, p x,yproduz os números, e terminamos!

Maçaneta da porta
fonte
Algumas vitórias básicas: altere a nova linha para $/e o loop while pode ser reduzido para (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Howard
4

Delphi XE3 (437 bytes || 897 874 sem bônus contado)

Ao pensar em como resolver isso com o bônus, pensei no seguinte.
Se você andar 4 dias, a célula 0,0 será alterada 4 vezes. A célula à direita é alterada duas vezes mais que a célula abaixo dela.
Se houver um número desigual de dias e o número na célula começar com 1, a célula à direita terá mais um que a célula abaixo e o contrário, se a célula for 0.

Ao fazer isso em cada célula, você pode ver se o valor final deve ser alterado por: A célula foi alterada X vezes. se X mod 2> 0, mude a célula.

Resultados no seguinte código:
{Whispers at JohnChen902} recebo seu voto positivo agora? : 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.
Teun Pronk
fonte
Você ainda não recebeu meu voto. Eu estava a jantar. (Voto a favor)
johnchen902
4

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

Aqui está a minha solução. É semelhante à solução do user2357112 , mas há várias diferenças:

  • Primeiro, despacho os horários de visita à direita e na parte inferior, em vez de calculá-los da parte superior e esquerda.
  • Segundo, faço tudo (lendo as entradas, despachando, rastreando a localização do homem) simultaneamente.
  • Terceiro, mantenho apenas uma linha de memória.
#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";}

Aqui está a versão não destruída:

#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;
}
johnchen902
fonte
Essas três diferenças tornam as coisas muito mais tensas. Podemos reduzir a indexação e combinar várias estruturas de dados redundantes. A lógica para enviar as visitas adiante é muito mais curta que a lógica para receber visitas das células anteriores. As condições de contorno horizontal são tratadas simplesmente estendendo a estrutura de dados para um espaço extra à direita, e as condições de contorno vertical não são um problema.
User2357112 suporta Monica
Promovi sua resposta e incorporei os conceitos em meu próprio código. Até agora, eles tiraram 84 bytes da minha solução, uma melhoria de 30%.
User2357112 suporta Monica
Suspeito que você consiga salvar alguns bytes sem fazê-lo --*o;. Em vez disso, alterne qual caso move o cara para baixo e qual caso move o cara para a direita.
User2357112 suporta Monica
@ user2357112 Implementado, mas o comprimento do código aumentou devido a um erro anterior (deveria ter sido 218 bytes).
precisa saber é o seguinte
3

Python, 177 bytes

Minha primeira tentativa no Code Golfing, desculpe se entendi algo errado aqui! Código usado para capturar a entrada com base no código do usuário2357112.

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

Entrada:

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

Resultado:

0 4
segfaultd
fonte
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)
}

Uso:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
lambruscoAcido
fonte