Adamın nereye gideceğini tahmin et


17

Bir adam (0, 0)bir kasabanın kuzeybatı köşesinde boy hve genişlikte yaşıyor w. Her gün evinden sınıra yürür (?, w)veya (h, ?). Aşağıdaki örnekte adam (3, 3)bugüne gidiyor .

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

Adam her noktada bir miktar kayıt yapar ( +yukarıdaki örnekte). Bir noktaya her ulaştığında, eğer bit ise doğuya gider 1ve aksi halde güneye gider . Bittikten sonra bit ters çevrilir. Örneğin:

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)

Kasabanın büyüklüğü ve adamın kaydı göz önüne alındığında, adamın hedefini ngün sonra hesaplayın .

Giriş:

İlk satırda üç tamsayı vardır h, wve n.

Aşağıdaki hsatırlarda w, adamın kaydını gösteren tamsayılar vardır.

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

Çıktı:

İki tamsayı, ngünler sonra adamın hedefini gösterir .

Örnek Giriş:

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

Örnek Çıktı:

0 4

Basit kod:

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

puanlama:

  • UTF-8'de en düşük bayt sayısı kazanır.
  • Kodunuzun çalışma süresi bağımsızsa, npuanınızı% 50 azaltın.
    • Do not sadece tüm 1000000000 gün sonuçları hesaplamak veya bu bonusu almak için benzer aptalca bir şey. Etkili bir algoritma bulun!

2 şey anlamadım. Çıktı, bazen diğer zamanlarda 0 dizini kullanırsınız. Bu nasıl çalışıyor? Sınır + 1 gibi mi olmalı? İkinci şey puanlama ile ikinci satır. Ne demek istiyorsun?
Teun Pronk

4. Gün 3,2 çıktısı vermeli mi?
Teun Pronk

2
Ne olursa olsun n, kodum tüm 1000000000 günün sonuçlarını hesaplar ve ardından sonucu çıkarırsa, nhala% -50 bonus alır mıyım?
user12205

@ şimdi böyle koy, mantıklı değil mi? Bunun için teşekkürler: P
Teun Pronk

@TeunPronk Evet. Bu benim hatam.
johnchen902

Yanıtlar:


7

GolfScript, 52.5 (% 50 bonus ile 105 karakter)

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

Sürüm çok etkilidir ve büyük değerler için bile çevrimiçi olarak test edilebilir .

User2357112'nin çözümüne benzer bir yaklaşım kullanır .


1
Lütfen bir açıklama istemeyin ;-) Bu canavarı kırmadan ve hata ayıklamadan bile değiştiremiyorum korkunç.
Howard

13

Python 2, 192 bayt * 0.5 bonus = 96

Bu problemi etkili bir şekilde çözmek için, anahtar yolun gerçekleştirilmesi, alınan yolların kesin olarak belirlenmesine gerek kalmadan, yukarıdaki ve soldaki hücrelerin kaç kez ziyaret edildiğine bağlı olarak her bir hücrenin kaç kez ziyaret edildiğini hesaplayabilmemizdir. Etkili bir şekilde, nyolculukları bir kerede simüle eder ve her bir hücrenin kaç kez kullanıldığını takip ederiz .

Johnchen902'nin çözümünden ilham alan itme tabanlı yaklaşım sayesinde önemli iyileştirme :

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

Önceki, çekme tabanlı uygulama:

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

Orijinal, disksiz sürüm:

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
Sen kısaltabilir not için 1^ve durumu yazılabilir uzun eğer f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Howard

@Howard: Teşekkürler. Düzenlemeler uygulandı.
user2357112 Monica

1
Eğer izin verirseniz rbir parametre (almaya r = lambda x: ...), o zaman kısaltabilirsiniz g=[r()for i in x]için g=map(r,x).
Roberto Bonvallet

@RobertoBonvallet: Evet. Tavsiye uygulandı.
user2357112 Monica

8

Yakut, 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

İlk satır, *bir değişkendeki ilk girdi satırını, diğerinde ise girdinin geri kalanını almak için operatörü kullanır . Daha sonra, bir iişlev dönüştürmek için tanımlandığı "1 2 3 4"INTO [1, 2, 3, 4]hem uygulanır, lve n. ( xve ydaha sonra kullanılmak üzere kaydedilir.)

n[-1]son öğesidir n, bu nedenle aşağıdaki blok (simülasyon) birçok kez yürütülür. İlk olarak xve ysıfıra ilklendirilirler (bloğun dışında ilan edilirler, böylece kapsamları yeterince büyüktür) ve daha sonra oldukça açıklayıcı olan simülasyon hattı yürütülür , ancak yine de bazı yorumlar:

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

Düzenleme: Howard tarafından sağlanan yeni simülasyon hattı, teşekkürler! Nasıl çalıştığını anladığımdan eminim ama bir açıklama eklemek için zamanım yok, bu yüzden daha sonra eklenecek.

Son olarak, p x,ysayıları çıktılar ve bitti!


Bazı temel kazançlar: yeni satırı değiştirin $/ve while döngüsü azaltılabilir (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Howard

4

Delphi XE3 (437 bayt || 897 874 bonus sayılmaz)

Bunu bonus ile nasıl çözeceğinizi düşünürken aşağıdakileri düşündüm.
4 gün yürürseniz, hücre 0,0 4 kez değiştirilir. Sağındaki hücre, altındaki hücre kadar iki kez değiştirilir.
Düzgün olmayan sayıda gün varsa ve hücredeki sayı 1 ile başlarsa, sağdaki hücre alttaki hücreden bir tane daha, hücre ise 0 ise başka bir yol alır.

Bunu her hücre için yaparak son değerin değiştirilip değiştirilmeyeceğini görebilirsiniz: Hücre X kez değiştirildi. X mod 2> 0 ise hücreyi değiştirin.

Aşağıdaki koddaki sonuçlar:
{Whispers at JohnChen902} Şimdi oyunuzu alabilir miyim? : 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.

Henüz oyumu almadınız. Akşam yemeği yiyordum. (Olumlu oy)
johnchen902

4

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

İşte benim çözümüm. User2357112'nin çözümüne benzer , ancak birkaç fark vardır:

  • İlk olarak, ziyaret zamanlarını üstten ve soldan hesaplamak yerine sağa ve alta gönderirim .
  • İkincisi, her şeyi yaparım (giriş okuma, gönderme, adamın yerini izleme) aynı anda.
  • Üçüncü olarak, sadece bir satır bellek tutuyorum.
#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";}

İşte ungolfed sürümü:

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

Bu üç farklılık işleri çok daha tersine çevirir. Endekslemeyi kısaltabilir ve birkaç gereksiz veri yapısını birleştirebiliriz. Ziyaretleri ileri itme mantığı, önceki hücrelerden ziyaret çekme mantığından çok daha kısa çıkıyor. Yatay sınır koşulları, veri yapısının sağa doğru fazladan bir alan genişletilmesiyle ele alınır ve dikey sınır koşulları bir sorun oluşturmaz.
user2357112

Cevabınızı onayladım ve kavramları kendi koduma dahil ettim. Şimdiye kadar, benim çözümümden 84 bayt aldılar,% 30'luk bir iyileşme.
user2357112

Bazı baytları yapamayacağınızdan şüpheleniyorum --*o;ve bunun yerine, bu durumda adamı aşağı taşıyorsunuz ve hangi durumda adamı sağa taşıyorsunuz.
user2357112 Monica

@ user2357112 Uygulandı, ancak önceki bir hata nedeniyle kod uzunluğu arttı (218 bayt olmalı).
johnchen902

3

Python, 177 bayt

Code Golfing benim ilk denemede, burada yanlış bir şey varsa çok üzgünüm! Kullanıcı2357112 koduna göre girdiyi almak için kullanılan kod.

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

Giriş:

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

Çıktı:

0 4

2

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

Kullanımı:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.