Prédisez où l'homme ira

17

Un homme vit dans le coin nord-ouest (0, 0)d'une ville de hauteur het de largeur w. Chaque jour, il marche de son domicile à la frontière (?, w)ou (h, ?). Dans l'exemple suivant, l'homme va (3, 3)aujourd'hui.

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

L'homme enregistre un peu à chaque point ( +dans l'exemple ci-dessus). Chaque fois qu'il atteint un point, il va vers l'est si le bit est 1et vers le sud sinon. Le mors est retourné après son départ. Par exemple:

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)

Compte tenu de la taille de la ville et du dossier de l'homme, calculez la destination de l'homme après plusieurs njours.

Contribution:

Dans la première ligne sont trois entiers, h, wet n.

Dans les hlignes suivantes sont des wnombres entiers, dénotant le dossier de l'homme.

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

Production:

Deux entiers, indiquant la destination de l'homme après des njours.

Exemple d'entrée:

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

Exemple de sortie:

0 4

Exemple de code:

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

Notation:

  • Nombre d'octets le plus bas dans les victoires UTF-8.
  • Si le temps d'exécution de votre code est indépendant de n, réduisez votre score de 50%.
    • Ne vous contentez pas de calculer les résultats de tous les 1000000000 jours ou de faire quelque chose de stupide pour obtenir ce bonus. Trouvez un algorithme efficace!
johnchen902
la source
2 choses que je ne comprends pas. La sortie, parfois vous utilisez 0 index d'autres fois que vous ne le faites pas. Comment ça marche? Doit-il être comme border + 1? La deuxième chose est la deuxième ligne avec la notation. Que voulez-vous dire par là?
Teun Pronk
Le jour 4 devrait produire 3,2 à droite?
Teun Pronk
2
Si, quoi qu'il en nsoit, mon code calcule les résultats de tous les 1000000000 jours, puis affiche le résultat de n, ai-je toujours le bonus de -50%?
user12205
@ace maintenant tu le mets comme ça, ça a du sens n'est-ce pas? Merci pour cela: P
Teun Pronk
@TeunPronk Oui. C'est de ma faute.
johnchen902

Réponses:

7

GolfScript, 52,5 (105 caractères avec 50% de bonus)

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

La version est très efficace et peut être testée en ligne même pour des valeurs importantes.

Il utilise une approche similaire à la solution de user2357112 .

Howard
la source
1
S'il vous plaît ne demandez pas d'explication ;-) Je ne peux même pas le changer sans casser et déboguer cette bête est horrible.
Howard
13

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

Pour résoudre ce problème efficacement, la réalisation clé est que nous pouvons calculer combien de fois chaque cellule est visitée en fonction du nombre de visites des cellules au-dessus et à gauche, sans avoir besoin de déterminer les chemins exacts empruntés. En effet, nous simulons les ndéplacements à la fois et gardons une trace du nombre de fois où chaque cellule est utilisée.

Amélioration substantielle grâce à une approche push inspirée de la solution 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

Implémentation précédente basée sur l'extraction:

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

Version originale non golfée:

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 prend en charge Monica
la source
1
Vous pouvez raccourcir le not à 1^et le long si la condition peut être écrite f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Howard
@Howard: Merci. Modifications appliquées.
user2357112 prend en charge Monica
1
Si vous autorisez rà prendre un paramètre ( r = lambda x: ...), vous pouvez le raccourcir g=[r()for i in x]en g=map(r,x).
Roberto Bonvallet
@RobertoBonvallet: Oui. Conseils mis en œuvre.
user2357112 prend en charge 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 première ligne utilise l' *opérateur pour saisir la première ligne d'entrée dans une variable et le reste de l'entrée dans une autre. Ensuite, une ifonction est définie pour se convertir "1 2 3 4"en [1, 2, 3, 4], qui est appliquée à la fois à let n. ( xet ysont enregistrés pour plus tard.)

n[-1]est le dernier élément de n, donc le bloc suivant (la simulation) est exécuté autant de fois. Tout d'abord, xet ysont initialisés à zéro (ils sont déclarés en dehors du bloc pour que leur portée soit suffisamment grande), puis la ligne de simulation est exécutée, ce qui est assez explicite, mais voici quand même quelques commentaires:

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: nouvelle ligne de simulation fournie par Howard, merci! Je suis sûr de bien comprendre comment cela fonctionne, mais je n'ai pas le temps d'ajouter une explication, donc une sera ajoutée plus tard.

Enfin, p x,ysort les chiffres, et c'est fait!

Poignée de porte
la source
Quelques gains de base: changez la nouvelle ligne en $/et la boucle while peut être réduite à (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Howard
4

Delphi XE3 (437 octets || 897 874 sans bonus compté)

En pensant à la façon de résoudre ce problème avec le bonus, j'ai pensé à ce qui suit.
Si vous marchez 4 jours, la cellule 0,0 est modifiée 4 fois. La cellule à sa droite est modifiée deux fois ainsi que la cellule située en dessous.
S'il y a un nombre de jours inégal et que le nombre dans la cellule commence par 1, la cellule de droite obtient un de plus que la cellule en dessous, et inversement si la cellule est 0.

En procédant ainsi pour chaque cellule, vous pouvez voir si la valeur finale doit être modifiée par: La cellule a été modifiée X fois. si X mod 2> 0, changez la cellule.

Résultats dans le code suivant:
{Whispers at JohnChen902} puis-je obtenir votre vote positif maintenant? : 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.

Non golfé

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
la source
Vous n'avez pas encore obtenu mon vote. J'étais en train de diner. (Voté)
johnchen902
4

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

Voici ma solution. Elle est similaire à la solution de user2357112 , mais il existe plusieurs différences:

  • Tout d'abord, j'envoie les heures de visite à droite et en bas, au lieu de les calculer à partir du haut et de la gauche.
  • Deuxièmement, je fais tout (lecture des entrées, répartition, suivi de la localisation de l'homme) simultanément.
  • Troisièmement, je ne garde qu'une seule ligne de mémoire.
#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";}

Voici la version non golfée:

#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
la source
Ces trois différences rendent les choses beaucoup plus difficiles. Nous pouvons raccourcir l'indexation et combiner plusieurs structures de données redondantes. La logique pour faire avancer les visites se révèle beaucoup plus courte que la logique pour tirer les visites des cellules précédentes. Les conditions aux limites horizontales sont gérées simplement en étendant la structure de données d'un espace supplémentaire vers la droite, et les conditions aux limites verticales ne sont pas un problème.
user2357112 prend en charge Monica
J'ai voté pour votre réponse et incorporé les concepts dans mon propre code. Jusqu'à présent, ils ont supprimé 84 octets de ma solution, soit une amélioration de 30%.
user2357112 prend en charge Monica
Je soupçonne que vous pourriez être en mesure d'économiser certains octets en ne le faisant pas --*o;, et en changeant plutôt le cas où vous déplacez le gars vers le bas et le cas où vous déplacez le gars vers la droite.
user2357112 prend en charge Monica
@ user2357112 Implémenté, mais la longueur du code augmente en raison d'une erreur précédente (il aurait dû être de 218 octets).
johnchen902
3

Python, 177 octets

Mon premier essai dans Code Golfing, donc désolé si je me suis trompé ici! Code utilisé pour saisir l'entrée en fonction du code de l'utilisateur2357112.

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

Contribution:

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

Production:

0 4
segfaultd
la source
2

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

Non golfé:

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)
}

Usage:

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