Bucles y bucles y bucles

16

El reto

Cree una función que, cuando se le da una entrada de arte ASCII (dirigiendo una ruta que eventualmente puede hacer un bucle), emite la longitud del bucle (si hay uno) y la longitud de la "cola" que conduce al bucle en una de las formularios a continuación.


Entrada

Su entrada debe pasarse a una función. A continuación se muestra un ejemplo de una entrada simple.

# --> # --> #
      ^     |
      |     |
      |     v
      # <-- #

Podrías visualizar los bloques anteriores así

La "cola" es un elemento, mientras que el bucle tiene cuatro largos.

Una más difícil:

            # --> # --> #
            ^           |
            |           |
            |           v
      # --> # <-- #     # --> #
      ^           ^           |
      |           |           |
      |           |           v
# --> #           # <-- # <-- #

Salida

Debe enviar a través de STDOUT o la alternativa más cercana a su idioma.

Sus dos enteros de salida deben ser la longitud de la cola y la longitud del bucle. Esta salida puede ser de dos formas.

  1. una cadena delimitada por espacios: "2 10"
  2. una serie de enteros: [2, 10]

Reglas

  • Cada bloque, o #, solo tendrá un único camino lejos de sí mismo.

  • Cada flecha tiene dos segmentos de línea y una cabeza.

  • El bloque inicial siempre estará en la columna más a la izquierda.

  • La entrada nunca será solo un bucle.


Ejemplo

# --> # --> # --> #
^     ^           |
|     |           |
|     |           v
#     # <-- # <-- #

Éste tiene una longitud de cola de 2 y una longitud de bucle de 6. A continuación, la cola y el bucle están separados.

Cola

# -->
^
|
|
#

Lazo

# --> # --> #
^           |
|           |
|           v
# <-- # <-- #

Las salidas correctas son [2, 6]y "2 6".

Si la entrada es solo una cola , la longitud del bucle es cero.

# --> # --> # --> #
                  |
                  |
                  v
        <-- # <-- #

Las salidas correctas para la entrada anterior son [6, 0]y"6 0"

Puertas de Zach
fuente
@orlp Creo que estás confundiendo entrada y salida.
Sanchises
1
¿Puede la entrada tener pedazos de ruta extra desconectados?
xnor
Creo que la introducción es confusa. Me hace pensar que el problema será sobre el análisis del programa, mientras que se trata de encontrar caminos en el arte ASCII.
xnor
He eliminado la introducción. Fue un poco confuso / engañoso. @xnor
Zach Gates
3
Relacionado: ¿Dónde está apuntando la flecha?
mınxomaτ

Respuestas:

11

JavaScript (ES6), 221 229

Una función con la entrada como parámetro, salida como una cadena a través de una ventana emergente (alerta).

Escanee repetidamente la entrada:
en cada paso

  • quitar el final de la cola
  • cuenta el '#' restante

Cuando no hay más cola para eliminar, el número de pasos hasta ahora es el tamaño de la cola y el número de '# restantes es el tamaño del bucle.

Todas las líneas nuevas dentro de los backticks son importantes y cuentan

Pruebe a ejecutar el fragmento a continuación con Firefox (no Chrome, ya que no es compatible ...)

F=s=>{s=`


${s}


`.split`
`.map(r=>[...r]);for(t=0,f=1;f;)s.map((r,y)=>r.map((c,x)=>c=='#'&&((r[x+2]+r[x-2]+s[y-1][x]+s[y+1][x]).match`[v<>^]`?++l:t+=(f=r[x-4]=r[x+4]=s[y-3][x]=s[y+3][x]=r[x]=1))),f=l=0);alert(t+' '+l)}

// Less golfed
U=s=>{
  s=`\n\n\n${s}\n\n\n`.split`\n`.map(r=>[...r])
  t=0
  do {
    f=l=0
    s.forEach((r,y) => {
      r.forEach((c,x) => {
        if (c == '#')
        {
          if (!(r[x+2] == '<' || r[x-2] == '>' || s[y-1][x] == 'v' || s[y+1][x] == '^'))
            t+=(f=r[x-4]=r[x+4]=s[y-3][x]=s[y+3][x]=r[x]=1)
          else
            ++l
        }
      })
    })
  } while(f)
  alert(t+' '+l)
}  

//Test

// Redefine console.log
alert=(...x)=>O.innerHTML+=x+'\n'

test=[`
# --> # --> #
      ^     |
      |     |
      |     v
      # <-- #`
,`
            # --> # --> #
            ^           |
            |           |
            |           v
      # --> # <-- #     # --> #
      ^           ^           |
      |           |           |
      |           |           v
# --> #           # <-- # <-- #`
,`
# --> # --> # --> #
^     ^           |
|     |           |
|     |           v
#     # <-- # <-- #`      
]

test.forEach(t=>(alert(t),F(t)))
<pre id=O></pre>

edc65
fuente
... ¿es correcto el operador de propagación? Es posible que desee nombrarlo de esta manera ya que existe en otros idiomas (como groovy) por otras sintaxis (*: list for groovy). Buena solución de todos modos!
Aaron
1
+1 Estaba pensando 'Debe haber una forma inteligente de hacer esto', se me ocurrió esta solución, solo para desplazarme hacia esta respuesta.
Sanchises
8

Rubí, 287 278 bytes

->i{n={}
g=->x{n[x]||=[0,p]}
t=y=0
i.lines{|l|x=0
l.chars{|c|x+=1
'><'[c]&&(r=c.ord-61;s,d=[y,x-4*r],[y,x+2*r])
'^v'[c]&&(r=c<?_?1:-1;s,d=[y+r*3,x],[y-r,x])
s&&(g[s][1]=g[d])[0]+=1}
y+=1}
c,*_,s=n.values.sort_by{|v|v[0]}
l=n.size
s[0]>1?((t+=1;c=c[1])while c!=s):t=l-=1
[t,l-t]}

Probarlo aquí .

Esto construye un hash (diccionario) de nodos. Para cada nodo, se almacena el número de conexiones entrantes y el siguiente nodo (posiblemente nulo).

Finalmente:

  • Si no hay un nodo con 2 conexiones entrantes (es decir, sin bucle), devuelva 0 para la cola y el número de nodos existentes para el bucle.
  • De lo contrario, comience a iterar desde el nodo con 0 conexiones entrantes (inicio) a través de next -> ...-> next hasta que se alcance el nodo con 2 conexiones entrantes (inicio de bucle). Devuelve los recuentos apropiados.

La versión legible del código está disponible aquí .

Cristian Lupascu
fuente
2

Rubí, 276

->s{a=k=w=s.index(r='
')*2+2
s=r*w+s+r*w
(s.size).times{|i|s[i,2]=='
#'&&(s[3+j=i+1]+s[j+w]+s[j-w]).strip.size<2&&(a=[j]
d=0
loop{("|-|-"[d])+?#=~/#{s[k=j+[-w,3,w,-3][d]]}/?(a.include?(k)&&break;a<<(j=k);d-=1):d=(d+1)%4}
)}
u=a.size
v=a.index(k)
t=(u-v)/4*2
print u/2-t," ",t}
Level River St
fuente