Dado un diagrama, encuentra X

19

Encuentra X

Me inspiraron las preguntas de matemáticas en las que se le pide a "Encontrar X" para una forma determinada. Originalmente, solo iba a tener el desafío de imprimir la ubicación x e y del carácter 'x' en una Cadena. Pero supuse que sería demasiado simple. Así que consideré el contexto en el que normalmente estaban, y decidí que encontrar la longitud de una Línea al lado de la x simplemente parecía apropiado.

Dada una entrada de cadena que contiene un Diagrama de 'líneas' ascii, así como una 'x' única y caracteres potencialmente basura, imprima la longitud de la única línea que tiene una 'x' directamente adyacente.

Ejemplos

Entrada:

|
|
|x
|
|

Ouput:

5

Entrada:

|\
| \x
|  \
|___\

Salida:

4

Entrada:

Diagram of a Wobbly Line:
IRRELEVANTTEXT____
____     ____/
    \___/ X ;)   
      x

Salida:

3

Entrada:

  ______________
 / ____________ \
 |/ __________ \|
 ||/ ________ \||
 |||/ ______ \|||
 ||||/      \||||
 |||||/  x  |||||
 |||||\_____/||||
 ||||\_______/|||
 |||\_________/||
 ||\___________/|
  \_____________/

Salida:

5

Notas

  • Los caracteres de línea válidos son \/_|
  • \ conecta la parte superior izquierda e inferior derecha de sí mismo.
  • / conecta la parte superior derecha e inferior izquierda de sí mismo.
  • _ conecta la izquierda y la derecha de sí mismo
  • | conecta la parte superior e inferior de sí mismo
  • Una línea siempre será recta y solo consistirá en uno de los caracteres de línea repetidos n veces.
  • La x siempre estará en minúscula, y siempre será la única en el diagrama.
  • Adjecent se refiere a que x es exactamente un carácter arriba, abajo o además.
  • La x siempre estará al lado de exactamente una línea.
  • Las pestañas nunca aparecerán en la entrada.
  • La entrada y la salida pueden tener cualquier formato aceptable.
  • Este es Code Golf, ¡así que el código más corto gana!
  • QUE TE DIVIERTAS. HAZLO. DIVIÉRTETE.

Implementación de referencia

Un taco
fuente
Buen desafío, pero creo que sería mejor garantizar que no haya pestañas en la entrada. Al decir que pueden ocurrir, está obligando efectivamente a todos a agregar código para convertir la pestaña en 4 espacios, lo que no tiene nada que ver con el desafío principal.
Level River St el
Sí, tienes un buen punto. Lo cortaré.
ATaco
Debe agregar un caso de prueba que tenga una forma similar @a las respuestas de la prueba de esfuerzo.
orlp
Desafío muy inteligente, espero ver algunas de las tácticas utilizadas para resolverlo
Darren H

Respuestas:

3

JavaScript (ES6), 165155 bytes

EDITAR: X y w en línea , para guardar algunos bytes más.

Golfizado (se supone que la entrada se rellena con espacios para hacer un rectángulo)

t=>([k=e=o=1,v=t.search`\n`+2,-1,-v].some(h=>i=({"|":v-1,"_":1,"/":v,"\\":v})[d=t[r=l=t.search`x`+h]]),[...t].map(_=>o+=(k&=t[l-=i]==d)+(e&=t[r+=i]==d)),o)

Expandido

/*
   G(<input string,space padded>) => line length
*/
G=t=> {

    /*
     ! Note that these two are inlined, in the "golfed" version !
     "w" - line "width"
     "x" - index of "x"
    */
    x=t.search`x`;
    w=t.search`\n`+1;

    /*
    Locate the "line"    
     l,r - left cursor, right cursor (for navigating along the line)
     k - left stop flag, e - right stop flag
     i - increment
     d - direction (char)
    */
    [k=e=o=1,v=w+1,-1,-w-1].some(h=>i=({"|":w,"_":1,"/":v,"\\":v})[d=t[r=l=x+h]]);

    /* 
     Travel along the line axis in both directions

     Note, the stop condition should rather be: while(k|e), 
     but we iterate over all the chars with map instead (as o is guaranteed to be < # chars),
     to save some space
    */
    [...t].map(_=>o+=(k&=t[l-=i]==d)+(e&=t[r+=i]==d));

    /* 
      Resulting line length
    */
    return o;
};

Prueba

G= 
t=>([k=e=o=1,v=t.search`\n`+2,-1,-v].some(h=>i=({"|":v-1,"_":1,"/":v,"\\":v})[d=t[r=l=t.search`x`+h]]),[...t].map(_=>o+=(k&=t[l-=i]==d)+(e&=t[r+=i]==d)),o);

[
G( 
 "| \n" +
 "| \n" +
 "|x\n" +
 "| \n" +
 "| \n"
),

G(
"|\\   \n" +
"| \\x \n" +
"|  \\ \n" +
"|___\\\n"
),

G(
"Diagram of a Wobbly Line:\n" +
"IRRELEVANTTEXT____       \n" +
"____     ____\/           \n" +
"    \___\/ X ;)           \n" +    
"      x                  \n"
),

G(
" ______________ \n"  +
"/ ____________ \\\n" +
"|/ __________ \\|\n" +
"||/ ________ \\||\n" + 
"|||/ ______ \\|||\n" +
"||||/      \\||||\n" +
"|||||/  x  |||||\n"  +
"|||||\_____\/||||\n" +
"||||\_______\/|||\n" +
"|||\_________\/||\n" +
"||\___________\/|\n" +
" \_____________\/\n"
)
]

Ejemplo de salida (si ejecuta esto en la consola de Google Chrome Developer Tools)

[5, 4, 3, 5]

zepelín
fuente
8

Python 3, 428 408 385 378 bytes

Funciona, pero tiene mucho potencial para jugar al golf. Estoy un poco oxidado

Asume que la entrada se rellena con espacios para hacer un rectángulo.

EDITAR: ¡Gracias a @Artyer por 23 bytes de ahorro!

EDIT2: Wow, me perdí por completo un ahorro de 6 bytes. Ahorró 1 más intercambiando lados de un cheque igual.

*i,=map(list,input().split('\n'))
r=c=s=q=e=w=0
o=lambda y,x:len(i[0])>x>=0<=y<len(i)
d='\/_|'
for l in i:
 if'x'in l:r=i.index(l);c=l.index('x')
for a,b in(1,0),(0,1),(-1,0),(0,-1):
 y,x=r+a,c+b;f=o(y,x)and i[y][x]
 if f in d:s=f;w=d.index(f);q,e=y,x
k=lambda y,x,g=[1,1,0,1][w],v=[1,-1,1,0][w]:o(y,x)and s==i[y][x]and(exec('i[y][x]=0')or 1+k(y+g,x+v)+k(y-g,x-v))
print(k(q,e))

Versión ampliada con explicación:

inputtt='''  ______________.
 / ____________ \
 |/ __________ \|
 ||/ ________ \||
 |||/ ______ \|||
 ||||/      \||||
 |||||/  x  |||||
 |||||\_____/||||
 ||||\_______/|||
 |||\_________/||
 ||\___________/|
  \_____________/'''

# First, we get the input from STDIN and make it
# into a doubly-nested array

*input_text,=map(list,inputtt.split('\n'))

# A pretty cool Python trick to assign 0 to
# mulitple variables at once.

row=col=line_letter=line_row=line_col=line_char_index=0

# A function to check if a certian row and col is
# in bounds or not. Uses python's comparator chaining

in_bounds=lambda y,x:len(input_text[0])>x>=0<=y<len(input_text)

# A string to store all the line characters.
chars='\/_|'

# Search for the x
for line in input_text:

 # If this line contains the x...
 if'x'in line:

     # Mark the row and column
     row=input_text.index(line);col=line.index('x')

# For each direction...
for down,right in(1,0),(0,1),(-1,0),(0,-1):

 # Move in that direction
 y,x=row+down,col+right

 # If the position is in bounds, mark the char at that position
 line_found=in_bounds(y,x)and input_text[y][x]

 # If the char is a line char, set all the variables saying we found it
 if line_found in chars:
  line_letter=line_found
  line_char_index=chars.index(line_found)
  line_row,line_col=y,x

recur=lambda y,x,\
       # Find which directions we are supposed to recur in based on the line char
       g=[1,1,0,1][line_char_index],v=[1,-1,1,0][line_char_index]:\
       # If the char is in bounds and we are still on the line...
       in_bounds(y,x)and input_text[y][x]==line_letter and\
       # Set the spot to a 0, so we won't go back, increment,
       # and recur in both directions
       (exec('i[y][x]=0')or 1+recur(y+g,x+v)+recur(y-g,x-v))

# Finally, print the answer
print(recur(line_row,line_col))
Azul
fuente
He hecho algunas sugerencias de golf en pastebin.com/zKENQUeR . Siéntase libre de usarlos si lo desea (Total: -18 bytes). Además, es posible que desee agregar <!-- language-all: lang-py -->para resaltar la sintaxis.
Artyer
@Artyer ¡Gracias! Fui estúpido por no hacer la mayoría de esos, pero no tenía idea sobre la barra invertida sin escape. Actualmente estoy en el móvil, ¡pero me aseguraré de incorporar sus sugerencias más adelante!
Azul
Ah, y uno más: primera línea para *i,=map(list,inputtt.split('\n'))( *i,hace iuna lista en lugar de un mapa) (-6 bytes más)
Artyer
Wow ... golf en su totalidad.
Erik the Outgolfer el
0

Lua, 480 bytes

Lua, siendo el lenguaje detallado, no supera la respuesta de Python. Pero no necesita hacerlo.

a=...s={}for _ in a:gmatch"[^\n]*"do s[#s+1]={}for S in _:gmatch"."do if S=="x"then x=#s[#s]+1y=#s end s[#s][#s[#s]+1]=S end end c="\\/_|"X={-1,1,1,0}Y={-1,-1,0,-1}for _,d in pairs({{x-1,y},{x,y-1},{x+1,y},{x,y+1}})do K=d[2]k=d[1]h=s[K]w=h and h[k]C=w and c:find(w)if C then n=1 j=k J=K while true do j=j+X[C]J=J+Y[C]if s[J]and s[J][j]==w then n=n+1 else break end end j=k J=K while true do j=j-X[C]J=J-Y[C]if s[J]and s[J][j]==w then n=n+1 else break end end print(n)break end end

Similar a mi implementación de referencia, pero toma una oportunidad real de jugar al golf y hace algunas cosas de manera más inteligente que antes. Sin embargo, probablemente podría jugar un poco mejor.

Con comentarios.

a=... -- Take the input from the command line.
s={}  -- Store the string as a 2D Table, instead of a multiline string.
for _ in a:gmatch"[^\n]*"do -- For each new row.
    s[#s+1] = {}            -- Make a new sub-table. This is our line.
    for S in _:gmatch"."do  -- For every character.
        if S=="x"then x=#s[#s]+1y=#s end -- If it's an x, mark down the X and Y position of it.
        s[#s][#s[#s]+1]=S                -- Push the character. This could probably be better golfed.
    end
end
c="\\/_|"   -- The ascii line characters.
X={-1,1,1,0}    -- Their X Directionals.
Y={-1,-1,0,-1}  -- Their Y Directionals.
                -- These are inversed to get their opposite direction.
for _,d in pairs({{x-1,y},{x,y-1},{x+1,y},{x,y+1}}) do -- For each up down left and right.
    K=d[2]  -- K = y
    k=d[1]  -- k = x
    h=s[K]  -- h = the yth row
    w=h and h[k]    -- w = the xth character of the yth row, if the yth row exists.
    C=w and c:find(w) -- C = the id of the ascii line character, if w existed.
    if C then
        n=1 -- n = the length of the line.
        j=k -- Temp x
        J=K -- Temp y
        while true do
            j=j+X[C] -- Increment j by the directional of the ascii.
            J=J+Y[C] -- Ditto. for J
            if s[J]and s[J][j]==w then -- if it's still the same.
                n=n+1 -- Add 1 to the length.
            else
                break -- Or stop.
            end
        end
        j=k -- Re-assign the temps as their original.
        J=K
        while true do
            j=j-X[C] -- Search in the other direction.
            J=J-Y[C]
            if s[J]and s[J][j]==w then
                n=n+1
            else
                break
            end
        end
        print(n) -- Print the length.
        break
    end
end
Un taco
fuente
-1

JavaScript (ES6), 175

Suponiendo que la entrada se rellena con espacios para hacer un rectángulo.

s=>(o=>{s.replace(/[_|\\/]/g,(c,p)=>[o,-o,1,-1].map(d=>s[p+d]=='x'?[q,k]=[p,c]:c));for(n=z=k>'_'?o:k>'\\'?-1:k>'/'?o-1:o+1;s[q+=z]==k||z<0&&(n=-1,z=-z);)n++})(~s.search`
`)||n

Menos golf

s=>{
  o = ~s.search`\n`; // offset between rows (negated)
  // look for a line character near an 'x'
  s.replace(/[_|\\/]/g, 
     (c,p)=> // for each line char 'c' in position 'p'
     [o,-o,1,-1].map(d=>s[p+d]=='x' // found a near 'x' ?
                        ?[q,k]=[p,c] // remember char and position
                        :c)
  );
  n=0;
  z=k>'_'?o:k>'\\'?-1:k>'/'?o-1:o+1; // offset to prev char of line
  while (s[q+=z]==k // move to left/top first
         || z<0 && (n=0,z=-z) // at left/top, go back and start counting
        )
    n++;
  return n-1;
}

Puntos de prueba en lugar de espacios para mayor claridad

f=
s=>(o=>{s.replace(/[_|\\/]/g,(c,p)=>[o,-o,1,-1].map(d=>s[p+d]=='x'?[q,k]=[p,c]:c));for(n=z=k>'_'?o:k>'\\'?-1:k>'/'?o-1:o+1;s[q+=z]==k||z<0&&(n=-1,z=-z);)n++})(~s.search`
`)||n

out=x=>O.textContent+=x

;["|.\n|.\n|x\n|.\n|.\n", "|\\...\n|.\\x.\n|..\\.\n|___\\\n"
,"Diagram of a Wobbly Line:\nIRRELEVANTTEXT...........\n____.....____/...........\n....\\___/.X.;)...........\n......x..................\n"
,"./ ____________ \\\n.|/ __________ \|\n.||/ ________ \\||\n.|||/ ______ \\|||\n.||||/      \\||||\n.|||||/  x  |||||\n.|||||\\_____/||||\n.||||\\_______/|||\n.|||\\_________/||\n.||\\___________/|\n. \\_____________/\n"].forEach(s=>out(s+f(s)+'\n\n'))
<pre id=O></pre>

edc65
fuente