El viajero O

26

El mundo es un conjunto de celdas de cinco por cinco. Se envuelve por todos lados. Se puede visualizar como ...

XXXXX
XXXXX
XXOXX
XXXXX
XXXXX

Eres un O. Te encanta viajar por el mundo, y lo haces de acuerdo con las siguientes reglas (deja que C sea el día actual):

  • En los primeros días, te sientes nostálgico. Regresa a donde empezaste ayer.
  • En días impares , sientes nostalgia. Mueva un paso horizontal más cerca de casa, si es posible, y un paso vertical más cerca de casa, si es posible. Ignora la envoltura mundial con el propósito de determinar la cercanía.
  • En incluso días, se siente aventurero. Mueve C / 2 pasos hacia el sur.
  • En días cuadrados , te sientes aventurero. Muévete hacia la pared este.
  • En los días de Fibonacci , el mundo se expande hacia el sur en una fila.
  • En días triangulares , el mundo se expande hacia el este en una columna.

Si se aplican dos o más de las reglas anteriores al mismo tiempo, aplíquelas en el orden indicado. Por ejemplo, en un primer día impar, primero regrese a donde comenzó ayer, y luego muévase un paso más cerca de casa.

Vives en el centro del mundo (inicial), es decir, posición (2,2), indexado a cero desde la esquina noroeste. Comienzas tu viaje allí el primer día.

Entrada

Un solo entero, N.

Salida

Sus coordenadas X e Y en el enésimo día, indexadas a cero desde la esquina noroeste, separadas por un solo espacio.

Caso de prueba con explicación

Dada una entrada de 3, la salida correcta es:

2 3

Podemos trabajar en esto un día a la vez. A partir del día 1, debemos aplicar los siguientes movimientos:

  1. Impar, cuadrado, fibonacci y triangular
  2. Prime, even y Fibonacci
  3. Prime, impar, Fibonacci y triangular

En forma visual:

     Día 1 Día 2 Día 3
XXXXX XXXXXX XXXXXX XXXXXXX
XXXXX XXXXXX XXXXXX XXXXXXX
XXOXX -> XXXXOX -> XXXXXX -> XXXOXXX
XXXXX XXXXXX XXOXXX XXXXXXX
XXXXX XXXXXX XXXXXX XXXXXXX
           XXXXXX XXXXXX XXXXXXX
                       XXXXXX XXXXXXX
                                   XXXXXXX

Casos de prueba adicionales

Cortesía de la solución de referencia de Martin Büttner (tenga en cuenta que solo debe generar una sola coordenada, no todas):

Input:  1     2     3     4     5     6     7     8     9     10    11    12    13    14     15    16    17    18    19    20    21    22    23
Output: 4 2   2 3   3 2   6 4   2 2   2 5   2 2   2 6   7 5   7 0   6 4   6 0   5 3   5 10   4 9   9 6   3 8   3 6   2 7   2 6   2 5   2 4   2 4

Este es el código de golf. La presentación más corta gana.

Perno de lluvia
fuente
66
Necesito hacer esto en O!
kirbyfan64sos

Respuestas:

4

Pyth, 157 156 153 bytes

=Z=b5aYA,2 2FNtUhQI&!tPN<1NA@Y_2)Iq*2/N2NA,G%+H/N2b)EL-+b<b2<2bAyM,GH)J@N2Iq/NJJA,tZH)=TU2W<hTNIqNeT=hbBE=TX_T1sT))=J0W!<NJIqN/*JhJ2=hZBE=hJ))aY(GH;jd,GH

Puedes probarlo aquí.

Este fue un problema divertido para el golf! Todavía me estoy acostumbrando a Pyth, pero es un lenguaje realmente genial.

Rhyzomatic
fuente
1
¡Bienvenido a Pyth! Un golf que veo enseguida: si quieres hacer una lista / tupla de 2 elementos, usa ,: para eso está.
isaacg
Hay más lugar para este campo de thoughout el código - (G%+H/N2b), (GH), (tZH).
isaacg
12

Haskell, 394 bytes

z=0<1
p d y c|all((0<).mod d)[2..d-1]=y|z=c
g x=x-signum(x-2)
e d(x,y)h|odd d=(g x,g y)|z=(x,mod(y+div d 2)h)
s d c@(_,y)w|d==(floor$sqrt$fromIntegral d)^2=(w-1,y)|z=c
f d a b m|b>d=m|b==d=(+1)<$>m|z=f d b(a+b)m
d%m@(w,h)|elem d[div(n*n-n)2|n<-[1..d+1]]=(w+1,h)|z=m
i=fst.c
j=snd.c
c d|d<1=((2,2),(5,5))|z=(s d(e d(p d(i$d-2)$i$d-1)$snd$j$d-1)$fst$j$d-1,d%(f d 1 1$j$d-1))
main=readLn>>=print.i

Definitivamente se puede optimizar y también después de verificar rápidamente la corrección parece que estoy obteniendo resultados diferentes a los publicados. Volveré y comprobaré más detenidamente mi código cuando tenga más tiempo ^^

Buen problema por cierto!

EDITAR: edité mi solución teniendo en cuenta los valiosos consejos dados por Zgarb . ¡Ahora funciona perfectamente!

EDIT2: gracias a nimi , he hecho el código aún más pequeño. Ahora también estoy haciendo las comprobaciones para pares e impares en una función en lugar de dos, lo que en general disminuye el recuento de 446 a 414 bytes.

EDITAR3: mejorado aún más de 414 a 400 bytes. Gracias nimi por otros 2 bytes, ¡estás en llamas! :)

EDIT4: 4 bytes más por nimi :)

basile-henry
fuente
2
Bienvenido a PPCG! Un par de consejos rápidos: 0<1es más corto otherwisey 0/=mod x yse puede acortar 0<mod x y. Además, 1==mod(d)2es odd dy 0==mod(d)2es even d.
Zgarb
@Zgarb buenos trucos, de hecho, soy bastante nuevo en todo esto del código de golf. ¿Cómo funciona en 0<1lugar de otherwisetrabajar?
basile-henry
1
Además, creo que su definición de números triangulares es incorrecta (supongo que está en la función t), ya que elem d[1..div(d*d-d)2]es cierto para todos d > 2.
Zgarb
otherwisees solo otro nombre para True.
Zgarb
Muchas gracias, sí que tiene razón que trató de hacer números triangulares demasiado rápido ...
Basile-Henry
5

C, 425 396 bytes

typedef struct{int x,y,b,r}c;S,p,n;s(d){return(S=sqrt(d))*S==d;}c m(d){if(!d)return(c){2,2,4,4};c q,l=m(d-1);for(p=1,n=d;--n;p=p*n*n%d);if(p&&d>1)q=m(d-2),l.x=q.x,l.y=q.y;if(d%2)l.x-=l.x>2?1:l.x<2?-1:0,l.y-=l.y>2?1:l.y<2?-1:0;else l.y+=d/2,l.y=l.y>l.b?l.y-l.b-1:l.y;if(s(d))l.x=l.r;if(s(5*d*d+4)||s(5*d*d-4))l.b++;if(s(8*d+1))l.r++;return l;}main(i){scanf("%d",&i);printf("%d %d",m(i).x,m(i).y);}

Hay partes en esto que podrían mejorarse, pero funciona para los casos de prueba .


Explicación

typedef struct {
    int x,y,b,r
} c; //c will hold the information for each day

//determines if a number is a perfect square
S,p,n;
s(d) {
    return (S=sqrt(d))*S==d;
}

c m(d) {
    if(!d)
        return (c){2,2,4,4}; //returns the initial information if the day is 0

    c q,l=m(d-1); //gets the information for the previous day
    for (p=1,n=d;--n;p=p*n*n%d); //tests if the number is prime

    if (p&&d>1)
        q=m(d-2),l.x=q.x,l.y=q.y; //changes the position to what it was at the end of the day 2 days ago if the day is prime
    if (d%2)
        l.x-=l.x>2?1:l.x<2?-1:0,l.y-=l.y>2?1:l.y<2?-1:0; //moves the position towards (2,2) if the day is odd
    else
        l.y+=d/2,l.y=l.y>l.b?l.y-l.b-1:l.y; //moves down if the day is even
    if (s(d))
        l.x=l.r; //moves east if the day is a perfect square
    if (s(5*d*d+4)||s(5*d*d-4))
        l.b++; //expands world down if the day is a fibonacci number
    if (s(8*d+1))
        l.r++; //expands world right if the day is a triangular number
    return l;
}

main(i) {
    scanf("%d",&i);
    printf("%d %d",m(i).x,m(i).y);
}
Chris Loonam
fuente
3

Perl 5, 284 bytes

@s=([2,2]);@n=(2,2);@f=(0,1);$w=$h=5;for(1..<>){$f[$_+1]=$f[$_]+$f[$_-1];$t[$_]=$_*($_+1)/2;$s[$_]=[@n];@n=@{$s[$_-1]}if(1 x$_)!~/^1$|^(11+?)\1+$/;($_%2)&&($n[0]-=($n[0]<=>2),$n[1]-=($n[1]<=>2))or$n[1]=($n[1]+$_/2)%$h;$n[0]=$w-1if(int sqrt$_)**2==$_;$h++if$_~~@f;$w++if$_~~@t}say"@n"

283 bytes, más 1 para el -Eindicador en lugar de-e

Mismo código pero con más espacios en blanco, más paréntesis y nombres de variables más largos:

@start=([2,2]);
@now=(2,2);
@fibonacci=(0,1);
$width = ($height=5);
for my $iterator (1 .. <>) {
  $fibonacci[$iterator+1] = $fibonacci[$iterator] + $fibonacci[$iterator-1];
  $triangular[$iterator] = $iterator * ($iterator+1) / 2;
  $start[$iterator] = [@now];
  @now = @{ $start[$iterator-1] } if ((1 x $iterator) !~ /^1$|^(11+?)\1+$/); # prime
  $now[0] -= ($now[0] <=> 2) , $now[1] -= ($now[1] <=> 2) if ($iterator % 2 != 0); # odd
  $now[1] = ($now[1] + $iterator / 2) % $height if ($iterator % 2 == 0); # even
  $now[0] = $width - 1 if ((int sqrt $iterator) ** 2 == $iterator); # square
  $height ++ if $iterator ~~ @fibonacci;
  $width ++ if $iterator ~~ @triangular;
}
say "@now";

Estoy seguro de que esto se puede jugar más.

msh210
fuente
2

Javascript, 361 359 bytes

N=>{for(c=1,x=y=v=w=j=k=2,h=z=5;c<=N;c++,j=v,k=w,v=x,w=y){m=Math;p=(n,c)=>n%c!=0?c>=n-1?1:p(n,++c):0;[x,y]=c==2||p(c,2)&&c!=1?[j,k]:[x,y];p=x=>x+(x<2?1:x>2?-1:0);c%2?[x,y]=[p(x),p(y)]:y+=c/2;m.sqrt(c)==~~m.sqrt(c)?x=z-1:0;f=(n,c,d)=>d<c?0:d==c?1:f(c,n+c,d);f(1,2,c)||c==1?h++:0;t=(n,c)=>n*++n/2==c?1:--n*n/2>c?0:t(++n,c);t(1,c)?z++:0;x%=z;y%=h}return x+" "+y}

El código utiliza la asignación de Destructuring . Solo es compatible con Firefox y Safari en este momento.

Explicación

N=>{
// C => the day, x,y => position, v,w => position at the start of the day, 
// j,k => position of yesterday
for(c=1,x=y=v=w=j=k=2,h=z=5;c<=N;c++,j=v,k=w,v=x,w=y){
    m=Math;

    // Prime Function for C > 2. Recursive call to save a loop.
    p=(n,c)=>n%c!=0?c>=n-1?1:p(n,++c):0;
    // Assign x and y to yesterday
    [x,y]=c==2||p(c,2)&&c!=1?[j,k]:[x,y];

    // Function to move closer to home
    p=x=>x+(x<2?1:x>2?-1:0);
    c%2?[x,y]=[p(x),p(y)]:y+=c/2;

    // Square check
    m.sqrt(c)==~~m.sqrt(c)?x=z-1:0;

    // Fibonnacci function for C > 1
    f=(n,c,d)=>d<c?0:d==c?1:f(c,n+c,d);
    f(1,2,c)||c==1?h++:0;

    // Triangle function
    t=(n,c)=>n*++n/2==c?1:--n*n/2>c?0:t(++n,c);
    t(1,c)?z++:0;

    // Stay in bounds
    x%=z;y%=h
}
// Output
return x+" "+y}
Naouak
fuente