Palabras en cadena estilo crucigrama

18

El reto

Dada una lista de palabras ["Programming", "Puzzles", "Code", "Golf"], las palabras son de estilo crucigrama:

      Programación
      tu
      z
      z
  G l
C oda
  ls
  F

El algoritmo

  • Tienes que procesar la lista en el orden dado.
  • Las palabras se imprimen en orientaciones alternas, comenzando horizontalmente .
  • Las dos palabras se cruzan en la primera letra de la primera palabra, que también está presente en la segunda palabra. Si esta letra aparece varias veces en la segunda palabra, tome la primera.

    Ejemplo : se
    ["no", "on"]convierte en:

    o
    n o
    

    y no

    n o
      n
    

Notas adicionales

  • Las palabras adyacentes en la lista tendrán al menos una letra común. ["Hi", "there"]No es una entrada válida.
  • Las palabras nunca chocarán. Siempre habrá suficiente espacio para imprimir una palabra en la primera intersección posible. ["Hello", "there", "end", "hello"]no es una entrada válida
  • La coincidencia distingue entre mayúsculas y minúsculas.
  • Las palabras pueden expandirse hacia la izquierda y hacia arriba.
  • Las letras de las palabras horizontales deben estar separadas por un espacio.
  • La lista de entrada contendrá al menos dos palabras.
  • Todas las palabras coincidirán con la expresión regular: [A-Za-z]+
  • Puede imprimir tantos espacios en blanco finales o nuevas líneas como desee, siempre que las palabras estén encadenadas correctamente.
  • Por otro lado, no puede agregar espacios en blanco iniciales adicionales. La palabra que más flota a la izquierda tiene cero espacios iniciales, las otras líneas tienen tantos espacios iniciales que todas se alinean correctamente.
  • Su programa debe ser capaz de manejar una cantidad arbitraria de palabras

Reglas

Casos de prueba

Lista de entrada en la primera línea, la salida comienza en la segunda línea.

["Pila", "Intercambio"]
    mi
    X
    C
    h
Tachuela S
    norte
    sol
    mi
["Este", "sitio", "graduado", "finalmente"]
    F
    es
    n T his
graduado
    le
    l
    y


¡Feliz codificación!

Denker
fuente
Ejemplo 2, la primera intersección posible entre sitey graduatedest
edc65
@ edc65 Me avergüenzo, lo arregló. ¡Gracias por la pista!
Denker

Respuestas:

3

JavaScript (ES6) 253

Como una función anónima con un parámetro de matriz

z=>(z.map((w,i)=>(i&&[...p].some((c,j)=>~(k=w.search(c))?i&1?[y-=k,x+=j]:[y+=j,x-=k]:0),[p=w,x<t?t=x:x,y<u?u=y:y]),t=u=x=y=0).map(([w,x,y],i)=>{x-=t,y-=u;for(c of w)(o[y]=o[y]||[])[x]=c,i&1?y++:x++},o=[]),o.map(r=>[...r].map(x=>x||' ').join` `).join`
`)

F=z=>(z.map((w,i)=>(i&&[...p].some((c,j)=>~(k=w.search(c))?i&1?[y-=k,x+=j]:[y+=j,x-=k]:0),[p=w,x<t?t=x:x,y<u?u=y:y]),t=u=x=y=0).map(([w,x,y],i)=>{x-=t,y-=u;for(c of w)(o[y]=o[y]||[])[x]=c,i&1?y++:x++},o=[]),o.map(r=>[...r].map(x=>x||' ').join` `).join`
`)

// Less golfed
F=z=>(
  z.map( // Step 1, find intersection points and relative position
    (w,i)=>(
      i && // for each word after thw first, find position respect the previous word
      [...p].some((c,j)=> // scan prec word using .some to exit at the first intersection found
         ~(k=w.search(c)) // search current char of p inside w
         ?i&1 // calc position, odd is vertical, even is horizontal
           ?[y-=k, x+=j] // returning an array so to have a truthy value
           :[y+=j, x-=k] // returning an array so to have a truthy value
         :0 // false = not found, continue the scan
      ),
      [p=w, // set preceding word
       x<t?t=x:x, // keep trace of min x
       y<u?u=y:y  // keep trace of min y
      ] // meanwhile, return word, x and y to be used in next step 
    ), t=u=x=y=0 // initializations
  )
  .map(([w,x,y],i)=>{ // Step 2, put char into the output array
      x-=t,y-=u; // normalize position respect to min values
      for(c of w) // for each char in word, set in the output array at the right place
        (o[y]=o[y]||[])[x]=c, 
        i&1?y++:x++ // increment x or y, again odd is vertical, even is horizontal
    }, o=[] // initialization of output array
  ),
  // Step 3, add the missing spaces and newlines
  o.map(r=>[...r].map(x=>x||' ').join` `).join`\n`
)

O.textContent=F(["This", "site", "graduated", "finally"])
<pre id=O></pre>

edc65
fuente
3

ANSI C, 385 390 caracteres

int N,a=1,x,y,d=1,u,k,l;int main(int c,char**v){for(;a<c;)N+=strlen(v[a++]);int H=N*2,W=N*4,m=H,n=N,q=m,w=n;char*p,F[W][H],*o;memset(F,32,W*H);for(a=1;a<c;a++){q=(x=m)<q?m:q;w=(y=n)<w?n:w;m=-1;for(p=v[a];*p;p++){F[x][y]=*p;if(m<0&&a<c-1&&(o=strchr(v[a+1],*p))){u=o-v[a+1];m=d?x:x-u*2;n=d?y-u:y;}if(d)x+=2;else y++;}d=!d;}for(l=w;l<H;l++){for(k=q;k<W;)putchar(F[k++][l]);putchar(10);}}

Llámalo así: ./crossword This site graduated finally

Versión sin golf:

int N,a=1,x,y,d=1,u,k,l;
int main(int c, char **v) {
    for(;a<c;)
        N+=strlen(v[a++]);
    int H = N*2, W = N*4, m = H, n = N, q=m, w=n;
    char *p,F[W][H], *o;
    memset(F, 32, W*H);
    for (a=1; a < c; a++) {
        q=(x=m)<q?m:q;
        w=(y=n)<w?n:w;
        m=-1;
        for (p=v[a]; *p; p++) {
            F[x][y] = *p;
            if (m<0&&a<c-1&&(o = strchr(v[a+1], *p))) {
                u = o-v[a+1];
                m = d ? x : x-u*2;
                n = d ? y-u : y;
            }
            if (d) x+=2; else y++;
        }
        d=!d;
    }
    for (l = w; l < H; l++) {
        for (k = q; k < W;)
            putchar(F[k++][l]);
        putchar(10);
    }
}

Gracias tucuxi por los consejos!

Thomas Oltmann
fuente
one char: a++)N+=strlen(v[a])=>)N+=strlen(v[a++])
tucuxi
otro: char F[W][H],*p=>char*p,F[W][H]
tucuxi
3 caracteres: eliminar {} de una sola línea for, reemplazar k++)putchar(F[k][l]con)putchar[k++][l]
tucuxi