Прогнозуйте, куди піде чоловік


17

Чоловік живе у північно-західному куточку (0, 0)міста з висотою hта шириною w. Щодня він ходить від свого дому до кордону (?, w)чи (h, ?). У наступному прикладі чоловік іде (3, 3)сьогодні.

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

Чоловік записує трохи у кожній точці ( +на прикладі вище). Кожен раз, коли він досягає точки, він іде на схід, якщо шматочок 1і на південь інакше. Біт перевертається після того, як він піде. Наприклад:

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)

Враховуючи розмір міста та людський облік, обчисліть місце призначення людини за nднями.

Вхід:

У першому рядку три цілі числа h, wі n.

У наступних hрядках - wцілі числа, що позначають чоловічий запис.

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

Вихід:

Два цілих числа, що позначають призначення людини через nдні.

Зразок введення:

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

Вибірка зразка:

0 4

Приклад коду:

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

Оцінка:

  • Найнижча кількість байтів у перемогах UTF-8.
  • Якщо час роботи вашого коду не залежить n, зменшіть свою оцінку на 50%.
    • Не просто обчислюйте результати всіх 1000000000 днів або робіть щось подібне нерозумно, щоб отримати цей бонус. Знайдіть ефективний алгоритм!

2 речі, які я не розумію. Вихід, іноді ви використовуєте 0 індексів у інші рази. Як це працює? Це має бути як межа + 1? Друга річ - другий рядок із зарахуванням балів. Як ви це маєте на увазі?
Teun Pronk

День 4 повинен виводити 3,2 правильно?
Теун Пронк

2
Якщо, незважаючи ні на що n, мій код обчислює результати всіх 1000000000 днів, то виводя результат n, чи все одно я отримую бонус -50%?
користувач12205

@ace тепер ви так ставите, це має сенс, чи не так? Дякую за це: P
Teun Pronk

@TeunPronk Так. Це моя вина.
johnchen902

Відповіді:


7

GolfScript, 52,5 (105 символів з 50% бонусом)

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

Версія дуже ефективна і може бути протестована в Інтернеті навіть на великі значення.

Він використовує підхід, подібний до рішення користувача2357112 .


1
Будь ласка, не вимагайте пояснень ;-) Я навіть не можу це змінити, не зламавши та налагоджуючи цього звіра, жахливо.
Говард

13

Python 2, 192 байти * 0,5 бонус = 96

Щоб ефективно вирішити цю проблему, головне усвідомлення полягає в тому, що ми можемо обчислити кількість відвідувань кожної комірки, виходячи з кількості відвідувань комірок вгорі та зліва, не потребуючи визначення точних шляхів. Ефективно ми моделюємо nпоїздки одразу і відстежуємо, скільки разів використовується кожна клітина.

Значне вдосконалення за рахунок підходу на основі поштовху, натхненного рішенням 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

Попередня реалізація на основі:

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

Оригінальна версія, що не використовується для гольфу:

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
Ви можете скоротити not до 1^і довге, якщо можна записати умову f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Говард

@Howard: Дякую Застосовані зміни.
user2357112 підтримує Моніку

1
Якщо ви дозволите rвзяти параметр ( r = lambda x: ...), то його можна скоротити g=[r()for i in x]до g=map(r,x).
Роберто Бонвальлет

@RobertoBonvallet: Так. Поради реалізовані.
user2357112 підтримує Моніку

8

Рубі, 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

Перший рядок використовує *оператор, щоб схопити перший рядок введення в одній змінній, а решту вводу в іншій. Потім визначається iфункція перетворення "1 2 3 4"в [1, 2, 3, 4], яка застосовується і до lі n. ( xі yзберігаються на потім.)

n[-1]є останнім елементом n, тому наступний блок (моделювання) виконується багато разів. По- перше, xі yне започатковано нулем (вони оголошені поза блоком , так що їх обсяг досить великий), а потім лінія моделювання виконується, що досить очевидно, але ось деякі коментарі в будь-якому випадку:

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

Редагувати: нова лінія моделювання, надана Говардом, дякую! Я впевнений, що розумію, як це працює, але я не встигаю додати пояснення, тому це буде додано пізніше.

Нарешті, p x,yвиводить цифри, і ми закінчили!


Деякі основні виграші: змініть новий рядок на, $/а цикл while можна зменшити до (x+=f=l[x][y]^=1;y+=f^1)while x<n[0]&&y<n[1]}.
Говард

4

Delphi XE3 (437 байт || 897 874 без нарахування бонусів)

Думаючи про те, як вирішити це з бонусом, я подумав про наступне.
Якщо ви ходите 4 дні, клітинку 0,0 змінюють 4 рази. Клітина праворуч змінюється вдвічі більше, ніж клітина під нею.
Якщо є нерівномірна кількість днів, і число в комірці починається з 1, осередок праворуч отримує на один більше, ніж комірка внизу, і навпаки, якщо комірка дорівнює 0.

Роблячи це для кожної комірки, ви можете побачити, чи слід змінити кінцеве значення на: Осередок було змінено X разів. якщо X mod 2> 0, то змініть комірку.

Результати в наступному коді:
{Шепіт у JohnChen902} я можу отримати вашу пропозицію зараз? : 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.

Безумовно

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.

Ви ще не отримали мого голосу. Я їв вечерю. (Upvoted)
johnchen902

4

C ++ 213 байт * 0,5 = 106,5

Ось моє рішення. Це схоже на рішення user2357112 , але є кілька відмінностей:

  • По-перше, я відправляю час відвідування праворуч і знизу, замість того, щоб обчислити їх зверху та зліва.
  • По-друге, я все роблю (читаючи введення, диспетчеринг, відстежую місцезнаходження людини) одночасно.
  • По-третє, я зберігаю лише один ряд пам’яті.
#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";}

Ось незворушний варіант:

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

Ці три відмінності роблять речі набагато складнішими. Ми можемо скоротити індексацію та поєднати кілька зайвих структур даних. Логіка просування візитів вперед виявляється набагато коротшою, ніж логіка витягування візитів із попередніх комірок. Горизонтальні граничні умови обробляються просто шляхом розширення структури даних додатковий простір праворуч, а вертикальні граничні умови не є проблемою.
user2357112 підтримує Моніку

Я підтримав вашу відповідь і включив ці поняття у свій власний код. Поки що вони взяли 84 байти з мого рішення, що на 30%.
user2357112 підтримує Моніку

Я підозрюю, що ви зможете зберегти кілька байтів, не роблячи цього --*o;, а замість цього перемикаючи, у якому випадку ви пересунете хлопця вниз, а в якому випадку ви пересунете хлопця праворуч.
user2357112 підтримує Monica

@ user2357112 Реалізовано, але довжина коду збільшується через попередню помилку (мала становити 218 байт).
johnchen902

3

Пітон, 177 байт

Перша моя спроба в коді Гольфінг, так що вибачте, якщо я тут щось не так! Код, який використовується для захоплення даних на основі коду user2357112.

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

Вхід:

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

Вихід:

0 4

2

R, 196 байт * 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)}

Безголовки:

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

Використання:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.