Предсказать, куда пойдет человек

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 дней или делайте глупости, чтобы получить этот бонус. Найдите эффективный алгоритм!
johnchen902
источник
2 вещи, которые я не понимаю. Выходные данные, иногда вы используете 0 индекса, а иногда нет. Как это работает? Должно ли это быть как граница + 1? Второе - вторая строчка с выигрышем. Как вы это имеете в виду?
Теун Пронк
День 4 должен вывести 3,2 верно?
Теун Пронк
2
Если, несмотря ни на что n, мой код вычисляет результаты всех 1000000000 дней, а затем выводит результат n, получу ли я бонус -50%?
user12205
@ а теперь ты так говоришь, это имеет смысл, не так ли? Спасибо за это: P
Теун Пронк
@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-,

Версия очень эффективна и может быть протестирована онлайн даже для больших значений.

Он использует подход, аналогичный решению user2357112 .

Говард
источник
1
Пожалуйста, не просите объяснений ;-) Я даже не могу изменить его, не сломав и не отладив этого зверя ужасно.
Говард
13

Python 2, 192 байта * 0.5 бонуса = 96

Чтобы эффективно решить эту проблему, ключевая реализация состоит в том, что мы можем вычислить, сколько раз каждая ячейка посещается на основе количества посещений выше и слева ячеек, без необходимости определять точные пройденные пути. По сути, мы моделируем nпоездки одновременно и отслеживаем, сколько раз используется каждая ячейка.

Существенное улучшение благодаря основанному на push подходе, основанном на решении 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
user2357112 поддерживает Monica
источник
1
Вы можете сократить not до 1^и долго, если условие может быть записано f=g[i][j]^v[i][j]&1 j+=f i+=1^f.
Говард
@ Ховард: Спасибо. Изменения применены.
user2357112 поддерживает Monica
1
Если вы разрешите rпринять параметр ( r = lambda x: ...), то можете сократить g=[r()for i in x]до g=map(r,x).
Роберто Бонваллет
@RobertoBonvallet: Да. Совет выполнен.
user2357112 поддерживает Monica
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, измените ячейку.

Результаты в следующем коде:
{Whispers at JohnChen902} я могу получить ваш отзыв сейчас? :П

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.
Теун Пронк
источник
Вы еще не получили мой голос. Я ужинал. (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;
}
johnchen902
источник
Эти три различия делают вещи намного более ужасными. Мы можем сократить индексирование и объединить несколько избыточных структур данных. Логика для продвижения посещений оказывается намного короче, чем логика для перемещения посещений из предыдущих ячеек. Горизонтальные граничные условия обрабатываются просто путем расширения структуры данных на дополнительное пространство вправо, и вертикальные граничные условия не являются проблемой.
user2357112 поддерживает Monica
Я проголосовал за ваш ответ и включил концепции в свой собственный код. Пока что из моего решения они взяли 84 байта, улучшение на 30%.
user2357112 поддерживает Monica
Я подозреваю, что вы могли бы сэкономить несколько байтов, не делая этого --*o;, и вместо этого переключая, в каком случае вы перемещаете парня вниз, а в каком случае вы перемещаете парня вправо.
user2357112 поддерживает Monica
@ user2357112 Реализовано, но длина кода увеличилась из-за предыдущей ошибки (должно было быть 218 байт).
johnchen902
3

Python, 177 байт

Моя первая попытка в Code Golfing, так что извините, если я что-то здесь не так понял! Код, используемый для получения ввода на основе кода 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
segfaultd
источник
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)}

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

Использование:

f(3,4,4,matrix(c(1,0,1,0,1,0,1,0,1,1,0,0),3))
3 2
lambruscoAcido
источник