El desafío del reloj de arena


43

El reloj de arena

Este reloj de arena tiene 60 "arenas de tiempo" y llena completamente cada cámara. El reloj tiene 19 caracteres de ancho y 13 caracteres de altura. Cada cámara tiene 5 filas de arena y hay una fila en el centro que puede contener 1 arena. La fila superior puede contener 17 arenas, la siguiente 15 y así sucesivamente (ver más abajo). Las arenas caen en la cámara inferior a razón de una arena por segundo.

       START                     3 SECONDS LATER               38 SECONDS LATER

███████████████████            ███████████████████            ███████████████████
█.................█   17       █..............   █   14       █                 █    0
██...............██   15       ██...............██   15       ██               ██    0
███.............███   13       ███.............███   13       ███.......      ███    7  
█████.........█████   09       █████.........█████   09       █████.........█████   09 
███████.....███████   05       ███████.....███████   05       ███████.....███████   05 
█████████.█████████   01       █████████.█████████   01       █████████.█████████   01 
███████     ███████            ███████  .  ███████            ███████  .  ███████  
█████         █████            █████    .    █████            █████    .    █████   
███             ███            ███      .      ███            ███....         ███
██               ██            ██               ██            ██...............██  
█                 █            █                 █            █.................█  
███████████████████            ███████████████████            ███████████████████   

El reto

Muestre el reloj de arena (no se requieren números ni encabezados) después de un cierto período de tiempo (0 ≤ t ≤ 60).

Reglas de codificación

  1. El reloj de arena debe verse exactamente como se muestra aquí. Puede reemplazar el carácter y / o el .carácter con lo que desee para adaptarse a su idioma (problemas de compatibilidad Unicode, ASCII).
  2. La entrada debe ser un número como 45 o 7. Visualice el reloj después de estos segundos.
  3. La salida puede mostrarse o guardarse en un archivo. No se requieren textos ni etiquetas adicionales como se muestra arriba, solo el reloj de arena es todo lo que necesitamos.
  4. Si el usuario ingresa t> 60, no tiene que manejar el error.

Puntos

  1. El código más corto gana.

No sé si soy solo yo, pero los relojes de arena se ven completamente diferentes en el editor que en la publicación misma. Probablemente sea porque el carácter █ no se muestra con el ancho adecuado.
Dennis

1
¿Un grano de arena toca la capa actual, luego se alinea a la izquierda un segundo después?
xnor

2
¿Cuál debería ser la salida para t == 59?
edc65

3
¡Felicidades por hacer la lista de preguntas de la red de Stack Exchange!
Alex A.

1
Esto no es realmente una respuesta, ya que no se ajusta a las especificaciones, pero eche un vistazo aquí para una presentación en Desmos. (Presione el botón de reproducción y ajuste la velocidad a 0.15x por ~ 1 unidad / segundo)
Conor O'Brien

Respuestas:


27

JavaScript ( ES6 ), 203 208 233 270 256 caracteres

Editar Revisado usando un bucle en lugar de una secuencia de llamadas.

Editar Se agregaron las filas superior e inferior que faltaban.

Una función que devuelve la salida. Ejecute el fragmento en Firefox para probar.

f=w=>[h='█'[R='repeat'](19),...[17,15,13,9,5,1,5,9,13,15,17].map((d,i)=>(t=i>5?-v:v,v-=i<5?d:1-d,e=' '[R](d/2),b='█'[R](10-d/2),b+('.'[R](t<d&&d-t)+e+' .'[i>4&w>i-6&t>=d|0]+e).slice(0,d)+b),v=w),h].join`
`

// Less golfed
F=
w=>[h='█'.repeat(19),
    ... [17, 15, 13, 9, 5, 1, 5, 9, 13, 15, 17].map(
     (d,i) => (
       t = i>5 ? -v : v,
       v -= i<5 ? d : 1-d, 
       e = ' '.repeat(d / 2),
       b = '█'.repeat(10 - d / 2),
       b + 
        ('.'.repeat(t < d && d - t) 
         + e + ' .'[i > 4 & w > i-6 & t >= d | 0]
         + e).slice(0,d)
       + b
     ), v = w
    ),
    h].join('\n')

// TEST            

O.innerHTML=f(+I.value)

function tick(d) {
  var i=+I.value+d
  I.value=i
  O.innerHTML=f(i)
}

var int=0;

function auto()
{
  function go()
  {
    var t = I.value;
    O.innerHTML=f(++t)
    if (t>70)t=0;
    I.value = t;
  }
  if (A.checked && !int)
  { 
    int = setInterval(go, 200);
  }
  else if (!A.checked && int)
  {
    clearInterval(int);
    int = 0;
  }
}
input[type=text] { width: 3em }
<button onclick='tick(-1)'>-</button>
<input type=text id=I value=0 onchange='tick(0)' >
<button onclick='tick(1)'>+</button>
<input type=checkbox id=A onclick='auto()'>Fly time
<pre id=O><pre>


55
Para mi curiosidad, ¿por qué se rechazó esto dos veces? No puedo encontrar ningún problema con eso.
manatwork

¡Esta respuesta es asombrosa ! ¡Ábrelo en Firefox, gente!
Cristian Lupascu

1
Buena respuesta, pero parece que faltan la parte superior y la base del reloj de arena.
Renae Lider

@manatwork no estoy seguro (por supuesto), pero sí hubo un error
edc65

Haga un setInterval (), javascript sería genial para eso:setTimeout( tick, 1000);
Martijn

18

Pitón 2, 200

t=input()+1
s=' '*t+'.'*60+' '*70
n=0
d=sum((1<t<56,2<t<48,3<t<36,4<t<22))
for c in'ctrplhdhlprtc':i=ord(c)-99;print[s[n+i:n:-1],[s[180-n-i+d:][:i],'.'][5+d*3>i>0]][n>59].center(i).center(19,'#');n+=i

xnor ha hecho una versión de 197 bytes en el chat .

Publicaría una explicación, pero he perdido la noción de cómo funciona realmente ...

Además, aquí hay una versión animada con maldiciones:

reloj de arena

from curses import*
w=initscr()

for t in range(1,61):
    s=' '*t+'.'*60+' '*70
    n=0
    d=sum((1<t<56,2<t<48,3<t<36,4<t<22))
    for i in 0,17,15,13,9,5,1,5,9,13,15,17,0:w.addstr([s[n+i:n:-1],[s[180-n-i+d:][:i],'.'][5+d*3>i>0]][n>59].center(i).center(19,'#')+"\n");n+=i
    w.refresh()
    w.clear()
    napms(999)

endwin()

1
¡Felicitaciones, me hiciste descubrir que las cadenas tienen un método centrado ()!
Dieter

13

Python 2.7, 362 356 347

e,c,x,a,b,n=' .#ab\n';R,r,s,l,T,m=range,str.replace,'',19,[1,2,3,5,7,9],-1
for t in[T,T[:m][::m]]:s+=''.join([n+x*y+c*(l-y*2)+x*y for y in t]);c=b
s=list(s)
for i in R(130,220,20):s[i]=a
for _ in R(input()):s[s.index('.')]=e;i=s.index(a)if a in s else 219-s[::m].index(b);s[i]='.'
for l in(x*l+r(r(''.join(s),a,e),b,e)+n+x*l).split(n):print l[::m]

reloj de arena

Salida a 38 segundos:

###################
#                 #
##               ##
###.......      ###
#####.........#####
#######.....#######
#########.#########
#######  .  #######
#####    .    #####
###...   .      ###
##...............##
#.................#
###################

2
¿Qué tipo de código Python es ese? Me encantaría aprender a codificar como ellos. Por favor guíe en la dirección correcta.
Rajat Saxena

1
No estoy seguro de si esta es una respuesta válida. Si observa el ejemplo que hizo durante 38 segundos, puede ver que el punto más bajo que aún está cayendo no está en la línea donde se alinean los puntos. (en la cuarta línea desde abajo, en el centro)
RononDex

3
@RononDex: Como se explica en los comentarios de la pregunta, el orden de llenado no es tan estricto: mi implementación pega los granos de arena a la izquierda de una manera que es ligeramente diferente de la pregunta, pero sigue siendo válida
dieta

3

C 544

Esto es lo que tengo hasta ahora para una solución C.

#include <stdio.h>
int main(int z,char **a){int r,i,y=i=0,v,d,t,m,s=atoi(a[1]),n[13]={0,43,28,15,6,1,0,1,5,13,25,39,0};char H[13][20];while(y<13){int x,b=x=i=0;v=y-6;t=3+abs(v);m=2*abs(v);d=t<m?t:m;d=9-d;if(d==0)d=10;while (b<d){H[y][b]='#';H[y][18-b]='#';b++;}while(x<19-2*b){if(x<=s-n[y])H[y][x+b]=v>0?' ':'.';else H[y][x+b]=v>0?'.':' ';x++;}if(s>58)r=0;else if(s==58)r=1;else if(s==57)r=2;else if(s==56)r=3;else if(s>38)r=4;else if(s>24)r=3;else if(s>12)r=2;else if(s>4)r=1;while(i<r){H[7+i][9]='.';i++;}H[y][19]='\n';y++;}fputs(H,stdout);}

Compilado con el siguiente comando:

gcc -w -o hourglass hourglass.c  // I realize I should have cast H as a char *, but since it works this way, I just decided to suppress the error from the compiler instead to save space.

Es cierto que este lenguaje tiene mucho volumen, que incluir la declaración fue un poco una desventaja al salir de los bloques, pero realmente estaba buscando una excusa para practicar el uso de C.

Espero que les guste mi solución, y avíseme si ve formas de mejorar.


2
Hay muchas maneras de mejorar, empeorando la C pero mucho más corta.
edc65

1
Sugerencias: en forlugar de where, en ?:lugar de if else, las variables globales int no necesitan int, includeno son necesarias. (Me gustan tus matemáticas)
edc65

1
317: r,i,y,x,b,d,n[]={0,43,28,15,6,1,0,1,5,13,25,39,0};char H[14][20];main(s,a)char**a;{for(s=atoi(a[1]);y<13;){b=x=i=0;d=abs(y-6);d+=3<d?3:d;d=9-d?9-d:10;r=s>55?59-s:s>38?4:s>24?3:s>12?2:s>4?1:r;for(;b<19;)H[y][b++]=35;for(;x<19-2*d;x++)H[y][x+d]=(x>s-n[y]?" .":". ")[y>6];for(;i<r;)H[7+i++][9]=46;H[y++][b]=10;}puts(H);}(cuidado, se agregan caracteres extraños e invisibles a comentarios largos como este)
edc65

3

Matlab, 252 bytes

La idea es construir una matriz que se vea así:

0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
0  17  16  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
0   0  32  31  30  29  28  27  26  25  24  23  22  21  20  19  18   0   0
0   0   0  45  44  43  42  41  40  39  38  37  36  35  34  33   0   0   0
0   0   0   0   0  54  53  52  51  50  49  48  47  46   0   0   0   0   0
0   0   0   0   0   0   0  59  58  57  56  55   0   0   0   0   0   0   0
0   0   0   0   0   0   0   0   0  60   0   0   0   0   0   0   0   0   0
0   0   0   0   0   0   0 116 117  61 118 119   0   0   0   0   0   0   0
0   0   0   0   0 108 109 110 111  62 112 113 114 115   0   0   0   0   0
0   0   0  96  97  98  99 100 101  63 102 103 104 105 106 107   0   0   0
0   0  82  83  84  85  86  87  88  64  89  90  91  92  93  94  95   0   0
0  66  67  68  69  70  71  72  73  65  74  75  76  77  78  79  80  81   0
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

A partir de ahí, es fácil llenar las entradas con las cadenas dependientes de n(llenar todas las entradas que son mayores ny menores que n+60con puntos)

function c=f(n);
b=zeros(13,19);
z=[0,17,32,45,54,59];
y=-2:3;
for k=2:6;
    d=k+sum(k>4:5);
    b(k,d:20-d)=z(k):-1:z(k-1)+1;
    b(14-k,d:19-d)=68+(z(k-1):z(k)-2)-k;
end;
b(8:12,11:19)=b(8:12,10:18);
b(7:12,10)=60:65;c=[ones(13,19)*32,''];
c(~b)='¶';c(n<b)=46;c(b>n+60)=32

Para n=38obtener esta salida:

¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶
¶                 ¶
¶¶               ¶¶
¶¶¶.......      ¶¶¶
¶¶¶¶¶.........¶¶¶¶¶
¶¶¶¶¶¶¶.....¶¶¶¶¶¶¶
¶¶¶¶¶¶¶¶¶.¶¶¶¶¶¶¶¶¶
¶¶¶¶¶¶¶  .  ¶¶¶¶¶¶¶
¶¶¶¶¶    .    ¶¶¶¶¶
¶¶¶...   .      ¶¶¶
¶¶...............¶¶
¶.................¶
¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶¶

2

Java, 712

La entrada se toma de la línea de comando. Maneja tanto los valores negativos para el tiempo como los más grandes de lo requerido.

enum H{;public static void main(String[]r){int x=0,y=0,z=0,l,t=Integer.parseInt(r[0]);String b="",d="█",e=" ",f=".",n="\n",j,k,a="███████████████████"+n;int[]w={17,15,13,9,5},v;int[][]h=new int[10][];for(;x<5;){l=w[x];v=(h[x++]=new int[l--]);l/=2;v[l]=++z;for(y=0;y++<l;){v[l-y]=++z;v[l+y]=++z;}}for(z=0;x>0;){l=w[--x];v=(h[9-x]=new int[l--]);v[l/2]=++z;}for(;x<5;){l=(w[x]-1)/2;v=h[9-x++];for(y=0;y++<l;){v[l-y]=++z;v[l+y]=++z;}}p(a);for(x=0;x<5;x++){l=w[x];j=b;for(y=0;y++*2<19-l;)j+=d;k=b;for(y=0;y<l;)k+=t<h[x][y++]?f:e;p(j+k+j+n);}j="█████████";p(j+f+j+n);for(;x>0;){l=w[--x];j=b;for(y=0;y++*2<19-l;)j+=d;k=b;for(y=0;y<l;)k+=t<h[9-x][y++]?e:f;p(j+k+j+n);}p(a);}static void p(String s){System.out.print(s);}}

salida:

time: 0
███████████████████
█.................█
██...............██
███.............███
█████.........█████
███████.....███████
█████████.█████████
███████     ███████
█████         █████
███             ███
██               ██
█                 █
███████████████████

time: 1
███████████████████
█........ ........█
██...............██
███.............███
█████.........█████
███████.....███████
█████████.█████████
███████  .  ███████
█████         █████
███             ███
██               ██
█                 █
███████████████████

time: 9
███████████████████
█....         ....█
██...............██
███.............███
█████.........█████
███████.....███████
█████████.█████████
███████  .  ███████
█████    .    █████
███      .      ███
██       .       ██
█      .....      █
███████████████████

time: 41
███████████████████
█                 █
██               ██
███..         ..███
█████.........█████
███████.....███████
█████████.█████████
███████  .  ███████
█████    .    █████
███   .......   ███
██...............██
█.................█
███████████████████

Llena la arena desde el centro expandiéndose hacia afuera. Probablemente pueda jugar más al golf si me da pereza saber cómo llena la mitad inferior y vacía la mitad superior. Pero por ahora me gusta bastante.


2

Haskell 512 Bytes

h=[17,15,13,9,5,1];b=drop 1$reverse h;n#s=[1..n]>>[s];s='.';n =' ';c q=(q#n)++(60-q)#s;f q|q<=5=q#s|3>2=g#s where{g=foldl i 5 (scanl (+) 0 h);i x y=if q>x+y then x-1 else x};e q=j#s++(59-length(k q)-(j))#n where{j=q-length(f q)};l q=c q++k q++(reverse$e q);p _ []=[];p x y=reverse(z++take q x++z):p (drop (head y) x) (tail y)where{q=head y;z=replicate(div (19-q) 2) '|'};k q= (concat.map(\x -> z x ++ "." ++ z x).take (length.f$q)$b)where{z x=(div x 2)#n};m n=mapM_ putStrLn $ t ++ p (l n) (h++b) ++ t;t=[19#'|'] 

Entrada m 55

Salida

|||||||||||||||||||
|                 |
||               ||
|||             |||
|||||         |||||
|||||||.... |||||||
|||||||||.|||||||||
|||||||  .  |||||||
|||||.........|||||
|||.............|||
||...............||
|.................|
|||||||||||||||||||

Entrada m 48 salida

    |||||||||||||||||||
    |                 |
    ||               ||
    |||             |||
    |||||......   |||||
    |||||||.....|||||||
    |||||||||.|||||||||
    |||||||  .  |||||||
    |||||..       |||||
    |||.............|||
    ||...............||
    |.................|
    |||||||||||||||||||

1
Bienvenido a PPCG! Veo que ya jugó bastante al golf, pero aún queda mucho espacio en blanco innecesario, por ejemplo. circundante ++. También puede guardar algunos bytes predefiniendo lengthy reverse.
Laikoni el

1

C #, 382 410

aún podría ser posible reducirlo en unos pocos bytes ...

class Program{static void Main(){int u=60-22,d=u,i,j,k,l,m;var c=new char[260];var r=new int[]{0,17,15,13,9,5,1,5,9,13,15,17,0,54,45,32,17,0};for(i=0;i<13;){m=0;l=(19-r[i])/2-1;for(j=19;j>=0;){k=i*20+j--;var b=j>=l&&j<r[i]+l;if(i>6&b)c[k-r[i]+m++ +m]=r[i+6]<d&&d-->0||j==8&r[i+6]>d&&d-->0?'.':' ';else c[k]=i<7&b?u-->1?' ':'.':'█';}c[++i*20-1]='\n';}System.Console.WriteLine(c);}}

Fiddler - 38sec


¡Guay! ¿Cómo toma entrada?
isaacg

@isaacg, vaya, lo arreglaré más tarde hoy, sabía que era demasiado corto para la solución ac # :-) por ahora cambie u = 60-22 a otra cosa
Fredou

¿Por qué usas int u=60-22y no solo int u=38?
dev-masih

1

Ruby: 196 190 186 185 184 caracteres

u=[0,17,15,13,9,5].map{|i|(?.*i).center 19,?#}*$/
(?1..$*[0]).map{u[?.]=' '}
l=u.reverse
5.times{|i|l[p=i*20+9]==?.&&l[' ']&&(l[p]=?|)&&l[' ']=?.}
puts u,?#*9+?.+?#*9,l.tr('. | ',' .')

CW porque no se ajusta exactamente a las muestras publicadas ya que esto consume arena a partir de la izquierda. Principalmente solo una demostración de String.[]=método.

Ejecución de muestra:

bash-4.3$ ruby hg.rb 38
###################
#                 #
##               ##
###      .......###
#####.........#####
#######.....#######
#########.#########
#######  .  #######
#####    .    #####
###      .   ...###
##...............##
#.................#
###################

Rubí: 215 caracteres.

Esto genera el resultado exacto requerido:

u=[0,17,15,13,9,5].map{|i|(?.*i).center 19,?#}*$/
(?1..$*[0]).map{u[?.]=' '}
l=u.reverse
5.times{|i|l[p=i*20+9]==?.&&l[' ']&&(l[p]=?|)&&l[' ']=?.}
puts ([u,?#*9+?.+?#*9,l.tr('. | ',' .')]*$/).split($/).map &:reverse

Ejecución de muestra:

bash-4.3$ ruby hg.rb 38
###################
#                 #
##               ##
###.......      ###
#####.........#####
#######.....#######
#########.#########
#######  .  #######
#####    .    #####
###...   .      ###
##...............##
#.................#
###################
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.