Dibujar mis contornos

25

Dada una matriz rectangular de elevaciones, dibuja sus contornos.

Tarea

Dos elementos xy yestán en el mismo nivel de contorno si floor(x/10) == floor(y/10). Por ejemplo, 52y 58están en el mismo nivel de contorno, pero 58y 64no lo están.

El acto de dibujar contornos se define de la siguiente manera: para cada elemento e, reemplácelo con una cadena de dos caracteres elegida de la siguiente manera:

  • el primer carácter es " "si el elemento a continuación eestá en el mismo nivel de contorno que eo si no hay ningún elemento a continuación ey de lo "_"contrario
  • el segundo carácter es " "si el elemento a la derecha eestá en el mismo nivel de contorno que eo no hay ningún elemento a la derecha ey "|"otra cosa

Los elementos dentro de las filas se unen, luego las filas se unen con nuevas líneas.

Ejemplo

Digamos que la entrada es [[5,20],[3,6]], visualizada como

5 20
3 6

Primero miramos 5. Dado que 3está en el mismo nivel de contorno que 5, el primer personaje está " ". Como 20no está en el mismo nivel de contorno que 5, el segundo carácter sí "|".

Ahora lo miramos 20. Como 6no está en el mismo nivel de contorno que 20, el primer carácter sí "_". Como no hay ningún elemento a la derecha de 20, el segundo carácter es " ".

Ahora lo miramos 3. Como no hay ningún elemento debajo 3, el primer carácter es " ". Como 6está en el mismo nivel de contorno que 3, el segundo personaje está " ".

Ahora lo miramos 6. Como no hay ningún elemento debajo 6, el primer carácter es " ". Como no hay ningún elemento a la derecha de 6, el segundo carácter es " ".

En base a estas cadenas de dos caracteres, hacemos reemplazos para obtener [[" |","_ "],[" "," "]]. Al unirlos, obtenemos una salida de

 |_ 
    

Reglas

  • La matriz de entrada siempre será rectangular y estará compuesta de enteros positivos.
  • Los espacios finales o las nuevas líneas pueden ser de cualquier cantidad (incluido 0) y no tienen que ser consistentes de ninguna manera.
  • No tiene que seguir el mismo algoritmo siempre que produzca los mismos resultados.
  • Su programa o función puede generar una cadena separada por una nueva línea, una lista de cadenas o equivalente.
  • Este es el , por lo que gana el código más corto en bytes.

Casos de prueba

input
output

[[1,5,8,9],[3,11,13,8],[7,14,10,9],[4,8,7,6]]
  _ _  
 |   | 
 |_ _| 

[[0,10,20,30,40,50,60,70,80,90],[0,0,10,10,20,20,30,30,40,40],[0,0,0,10,10,10,20,20,20,30],[0,0,0,0,10,10,10,10,20,20],[0,0,0,0,0,10,10,10,10,10],[0,0,0,0,0,0,10,10,10,10],[0,0,0,0,0,0,0,10,10,10],[0,0,0,0,0,0,0,0,10,10],[0,0,0,0,0,0,0,0,0,10],[0,0,0,0,0,0,0,0,0,0]]
 |_|_|_|_|_|_|_|_|_
   |_  |_ _|_ _|_ _
     |_    |_ _  |_
       |_      |_ _
         |_        
           |_      
             |_    
               |_  
                 |_


[[5,5,5,5,5,5,5,5,5,5,5],[5,10,10,10,10,10,10,10,10,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,25,30,25,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,10,10,10,10,10,10,10,10,5],[5,5,5,5,5,5,5,5,5,5,5]]
  _ _ _ _ _ _ _ _ _  
 |                 | 
 |    _ _ _ _ _    | 
 |   |         |   | 
 |   |    _    |   | 
 |   |   |_|   |   | 
 |   |         |   | 
 |   |_ _ _ _ _|   | 
 |                 | 
 |_ _ _ _ _ _ _ _ _| 

[[35,32,29,26,25,25,25,26,29,32,35],[32,28,25,22,20,20,20,22,25,28,32],[29,25,21,18,15,15,15,18,21,25,29],[26,22,18,14,11,10,11,14,18,22,26],[25,20,15,11,7,5,7,11,15,20,25],[25,20,15,10,5,0,5,10,15,20,25],[25,20,15,11,7,5,7,11,15,20,25],[26,22,18,14,11,10,11,14,18,22,26],[29,25,21,18,15,15,15,18,21,25,29],[32,28,25,22,20,20,20,22,25,28,32],[35,32,29,26,25,25,25,26,29,32,35]]
  _|             |_  
_|    _ _ _ _ _    |_
    _|         |_    
   |    _ _ _    |   
   |   |     |   |   
   |   |     |   |   
   |   |_ _ _|   |   
   |_           _|   
_    |_ _ _ _ _|    _
 |_               _| 
   |             |  
fireflame241
fuente
1
Ni siquiera comienzo a leer esto antes de darme cuenta de lo genial que será esto
Christopher

Respuestas:

6

Perl 6 , 135 bytes (131 caracteres)

{my$n="_";sub w{$^a.chop-$^b.chop??$n!!" "};my&q={|.[1..*],.tail};(($_ «[&w]».&q) ZZ~{$n="|";$_ «[&w]».map(*.&q)}()).map:{say |$_}}

Pruébalo en línea!

Ligeramente incólume:

{
    my $n = "_";
    sub w { $^a.chop - $^b.chop ?? $n !! " "};
    my &q = {|.[1..*],.tail};
    (
        ($_ «[&w]».&q)
        ZZ~
        {$n="|";$_ «[&w]».map(*.&q)}()
    ).map:{say |$_}
}

Explicación : Primero, definimos una variable $n(línea 2) y una función w(línea 3). Esta función devuelve un espacio si sus dos argumentos están en la misma "elevación", y el contenido de la variable de lo $ncontrario. En lugar de dividir entre 10 y pisos, abusamos del hecho de que los ints son Cool(pueden tratarse como cadenas) y los usamos choppara eliminar el último carácter (= dígito). Luego los restamos con calma, forzándolos nuevamente a números :—).

Después de eso (línea 4) creamos una función qque toma una lista y la devuelve con el primer elemento eliminado y el último elemento duplicado.

En las siguientes 3 líneas, vamos a hacer 2 matrices más a partir de la matriz de entrada: a la primera le falta la primera fila y la última fila está duplicada (es solo que .&q, usando .&, puede llamar a una función en cualquier cosa como si fuera un método: lo que está delante del punto es entonces el primer argumento), al otro le falta la primera columna y la última columna está duplicada (eso es .map(*.&q)).

Primero (línea 4) tomamos la matriz original $_, la "superponemos" con la matriz de "filas desplazadas" y usamos la función wcomo operador binario (eso es [&w]) en los elementos coincidentes. Ese pone un _lugar donde los elementos coincidentes están en las diferentes elevaciones, y lo contrario. Entonces obtenemos la mitad del resultado (solo los "primeros caracteres").

En la línea 6, hacemos lo mismo, pero primero cambiamos $na |, y ahora "superponemos" la matriz original con la matriz con columnas desplazadas. El resultado tiene una elevación |diferente y a la misma Estos son los "segundos personajes".

Ahora solo los combinamos juntos. Comprimimos las matrices con un zip con un concat (sí ...), lo que da como resultado una matriz de la forma original cuyo elemento son los 2 elementos coincidentes de las "medias soluciones" concatenadas. Finalmente, simplemente mapeamos sobre esta matriz (que es realmente una lista de listas). Cada una de estas listas se aplana y luego se sayedita (impresa con una nueva línea). Como saypuede tomar cualquier número de argumentos y los imprime todos sin separadores, haciendo que la nueva línea solo al final, obtengamos la imagen deseada en stdout. (Y el bloque devuelve una lista de Trues (cada sayuno devuelve uno True), pero a quién le importa).

Ramillies
fuente
+1 parabut who cares
HyperNeutrino
5

Jalea ,  25 23  22 bytes

-1 byte gracias a millas ( Ivectorises)

:⁵I;€0ao⁶
Zç”_Zż"ç”|$Y

Un programa completo que imprime el resultado. Como enlace monádico, toma una lista de listas de números, las elevaciones y devuelve una lista de listas, sin embargo, estas "filas" consisten en listas de "pares" de dos caracteres: si esto está bien, se puede guardar 1 byte al eliminarlo Y.

Pruébalo en línea!

¿Cómo?

:⁵I;€0ao⁶ - Link 1, assignCharacters (row-wise): list of lists of numbers; character, c
 ⁵        - literal 10
:         - integer division (vectorises)
  I       - incremental differences (vectorises) (zero if the same else non-zero)
     0    - literal 0
   ;€     - concatenate for €ach (rightmost edge of a row has no contour mark)
      a   - logical and (vectorises) with c (replace non-zeros with the contour character)
        ⁶ - literal space character
       o  - logical or (vectorises) (replace the zeros with spaces)

Zç”_Zż"ç”|$Y - Main link: list of lists of numbers, contours
Z            - transpose the input (get the columns)
  ”_         - literal underscore character, '_'
 ç           - call the last link (1) as a dyad with '_'
    Z        - transpose the result
          $  - last two links as a monad:
        ”|   -   literal pipe character, '|'
       ç     -   call the last link (1) as a dyad with '|'
      "      - zip with the dyadic operation:
     ż       -   zip (interleave the column-wise characters with the row-wise ones)
           Y - join with newlines
             - implicit print
Jonathan Allan
fuente
grr 3 bytes. +1 pero intentaré superarlo;)
HyperNeutrino
Solución independiente: ¡acabo de ver la suya es muy similar! te ahorra uno ...
Jonathan Allan
Puede guardar un byte usando cada uno en la unión en el asistente en :⁵I;€0ao⁶lugar de en el enlace principalZç”_Zż"ç”|$Y
millas del
@miles Oh wow, eso funciona? ¡Gracias! Me imaginé Ique no se vectorizaría así.
Jonathan Allan
Sí, Ivectoriza en la profundidad 1, y ambos ay ovectoriza en la profundidad 0
millas
3

Python 2 , 199 186 157 155 bytes

lambda a:(lambda x:'\n'.join(''.join('_ '[x==z]+'| '[x==y]for x,y,z in zip(r,r[1:]+r[-1:],q))for r,q in zip(x,x[1:]+x[-1:])))([[v/10for v in r]for r in a])

Pruébalo en línea!

Chas Brown
fuente
3

Jalea , 24 bytes

:⁵IṠ;€0
ZÇZị⁾_ +³Ç¤ị⁾| ¤

Pruébalo en línea!

Explicación

:⁵IṠ;€0           Helper Link; get contour data
:                 Floor division by
 ⁵                10
  I               Compute increments
   Ṡ              Sign; ±1 for different values and 0 for same values
    ;             Append
      0           Zero
     €            To each row
ZÇZị⁾_ +³Ç¤ị⁾| ¤  Main Link
Z                 Zip the input (for vertical contours _)
 Ç                Get the contour data
  Z               Zip the data (because it's zipped from the first Z)
   ị              Index into the string
    ⁾_            "_ "
       +          Add (vectorizing twice) to
        ³ ¤    ¤  Nilad starting from (input)
         Ç        Get contour data (horizontal contours |)
           ị      Index into the string
            ⁾|    "| "

-2 bytes gracias a Jonathan Allan

Hiperneutrino
fuente
Su solución puede acabar con el Y- devolverá una lista de listas de caracteres, lo cual creo que está bien (mientras que el mío tiene pares dentro de las "filas").
Jonathan Allan
@JonathanAllan oh sí cierto ... gracias!
HyperNeutrino
2

Python 2 , 226 bytes

l=[[j/10for j in i]for i in input()]
for i,j in enumerate(l[:-1]):print''.join('_ '[h==l[i+1][g]]+'| '[h==j[g+1]]for g,h in enumerate(j[:-1]))+'_ '[j[-1]==l[i+1][-1]]
print''.join(' '+'| '[i==j]for i,j in zip(l[-1],l[-1][1:]))

Pruébalo en línea!

Menos mal, eso era una maravilla para resolver la lógica. Ahora veo que Hyper Neutrino me ninja con una respuesta más corta, pero pasé demasiado trabajo en esto para no publicarlo. :PAGS

Además, puedo decir que esta es una forma increíble de hacer arte ASCII. Disculpe mientras hago un bote cargado más de estos.

totalmente humano
fuente
> ninja'd: amigo, han pasado 45 minutos
HyperNeutrino
Sí, no miré las respuestas ...: P
totalmente humano
Puede guardar 4 bytes definiendo una variable para en enumeratelugar de usar el nombre completo dos veces.
Jonathan Frech
218 bytes eliminando el primero enumerate(obs, tuve que eliminar algunas entradas para poder vincularlo aquí)
Felipe Nardi Batista
2

J, 58 bytes

f=.{~0==/@]
[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10

Pruébalo en línea!

Una función anónima que toma una matriz y genera los contornos.

Mucho espacio para mejorar aquí. No tuve tiempo para probar todos los casos de prueba, así que avíseme si hay algún problema. Intentaré jugar más al golf y explicaré más tarde.

(Rápido) Explicación

Función auxiliar: indexa en una cadena de longitud 2 en función de si el primer elemento de una matriz de 2 longitudes es igual al segundo. Si es igual, se indexa en el elemento cero, si es desigual, se indexa en el primero. Una matriz de 1 longitud siempre se indexa en el elemento cero de la cadena.

f=.{~0==/@]

Función principal

[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10

1:+<.@%&10 coloca cada elemento dividido entre 10 y agrega 1 (por lo que nunca obtendremos 0; esto es importante para la función auxiliar).

2 2((' _'f{."1),' |'f{.);.3corta la matriz en 2 x 2 segmentos si puede (de lo contrario, dará un segmento de 2 x 1, 1 x 2 o 1 x 1 cerca de los bordes) y aplica la función que se usa fpara comparar el elemento superior izquierdo con el superior derecha y el elemento superior izquierdo a la parte inferior izquierda.

(,/"2)aplana el resultado en la forma deseada. Realmente siento que debería poder evitar tener que usar esto (y muchas otras cosas, pero me estoy desviando).

col
fuente
2

JavaScript (ES6), 120 118 bytes

a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>((a[i+1]||0)[j]-c?'_':' ')+(b[j+1]-c?'|':' ')).join``).join`\n`

Donde \nrepresenta el carácter literal de nueva línea. Editar: Guardado 2 bytes gracias a @ Bálint.

f=
a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>((a[i+1]||0)[j]-c?'_':' ')+(b[j+1]-c?'|':' ')).join``).join`
`
;[
[[5,20],[3,6]]
,
[[1,5,8,9],[3,11,13,8],[7,14,10,9],[4,8,7,6]]
,
[[0,10,20,30,40,50,60,70,80,90],[0,0,10,10,20,20,30,30,40,40],[0,0,0,10,10,10,20,20,20,30],[0,0,0,0,10,10,10,10,20,20],[0,0,0,0,0,10,10,10,10,10],[0,0,0,0,0,0,10,10,10,10],[0,0,0,0,0,0,0,10,10,10],[0,0,0,0,0,0,0,0,10,10],[0,0,0,0,0,0,0,0,0,10],[0,0,0,0,0,0,0,0,0,0]]
,
[[5,5,5,5,5,5,5,5,5,5,5],[5,10,10,10,10,10,10,10,10,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,25,30,25,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,10,10,10,10,10,10,10,10,5],[5,5,5,5,5,5,5,5,5,5,5]]
,
[[35,32,29,26,25,25,25,26,29,32,35],[32,28,25,22,20,20,20,22,25,28,32],[29,25,21,18,15,15,15,18,21,25,29],[26,22,18,14,11,10,11,14,18,22,26],[25,20,15,11,7,5,7,11,15,20,25],[25,20,15,10,5,0,5,10,15,20,25],[25,20,15,11,7,5,7,11,15,20,25],[26,22,18,14,11,10,11,14,18,22,26],[29,25,21,18,15,15,15,18,21,25,29],[32,28,25,22,20,20,20,22,25,28,32],[35,32,29,26,25,25,25,26,29,32,35]]
].forEach(a=>document.write(['<pre>','</pre>'].join(f(a))));

Neil
fuente
Puede convertir las (a[i] || [])[j]construcciones a(a[i] || 0)[j]
Bálint
Además, en el último join`\n`podría quitar la \npieza y reemplazarla con una nueva línea real
Bálint
114 bytes:a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>" _"[(a[i+1]||0)[j]-c&1]+" |"[b[j+1]-c&1]).join``).join`<new line here>`
Bálint
@ Bálint Bah, sigo olvidando hacer esa \nparte; Pruebo en un REPL para que las nuevas líneas literales se interpongan en el camino.
Neil
@ Bálint Pero su última sugerencia falla para el ejemplo original, que he agregado a la lista de resultados.
Neil
1

Protón , 202 bytes

R=(L=len)+range
k=[map((//)&10,r)for r:eval(input())]
d=(x,y,X,Y)=>X>=L(k)or Y>=L(k[X])or k[x][y]==k[X][Y]
print('\n'.join(map(''.join,[['_ '[d(x,y,x+1,y)]+'| '[d(x,y,x,y+1)]for y:R(k[x])]for x:R(k)])))

Pruébalo en línea!

-2 bytes gracias a Jonathan Frech
-15 bytes cambiando a Proton en lugar de Python 2

Hiperneutrino
fuente
Puede guardar dos bytes reemplazando lencon Ly definiendo L=len;.
Jonathan Frech
1

Java 8, 200 170 169 bytes

a->{String r="";for(int l=a.length,i=0,j;i<l;i++,r+="\n")for(j=0;j<l;r+=(i>l-2||a[i][j]/10==a[i+1][j]/10?" ":"_")+(j++>l-2||a[i][j-1]/10==a[i][j]/10?" ":"|"));return r;}

Explicación:

Pruébalo aquí.

Tenga en cuenta que la división de enteros en Java automáticamente pisos.

a->{                   // Method with 2D int-array as parameter and String return-type
  String r="";         //  Result-String
  for(int l=a.length,  //  Length of the input array
      i=0,j;           //  Index integers
      i<l;i++,         //  Loop (1) over the rows of the input array
          r+="\n")     //  and append a new-line to the result after every iteration
    for(j=0;j<l;       //   Inner loop (2) over the columns of a row
      r+=              //    Append the String with:
         (i>l-2        //      If it's the last row,
         ||a[i][j]/10==a[i+1][j]/10?
                       //      or the current and next rows are equal floored/10:
          " "          //       Use a space
         :             //      Else:
          "_")         //       Use a "_"
        +              //     Plus
         (j++>l-2      //      If it's the last column in the row,
         ||a[i][j-1]/10==a[i][j]/10?
                       //      or the current and next columns are equal floored/10:
          " "          //       Use a space
         :             //      Else:
          "|")         //       Use "|"
    );                 //   End of column loop (2)
                       //  End of row-loop (1) (implicit / single-line body)
  return r;            //  Return the result-String
}                      // End of method
Kevin Cruijssen
fuente
1

R, 159 bytes

f=function(m){M=m%/%10;a=cbind(0,t(apply(M,1,diff)));b=rbind(apply(M,2,diff),0);a[!!a]="|";b[!!b]="_";M[]=gsub("0"," ",paste0(a,b));write(t(M),"",ncol(m),,"")}

Con nuevas líneas y hendiduras:

f=function(m){
    M=m%/%10
    a=cbind(0,t(apply(M,1,diff))) #row-wise difference
    b=rbind(apply(M,2,diff),0) #column-wise difference
    a[!!a]="|"
    b[!!b]="_"
    M[]=gsub("0"," ",paste0(a,b)) # M[] is a trick to force the result to have the same structure as M
    write(t(M),"",ncol(m),,"")
    }

Hace la división entera de la matriz, mide las diferencias entre las filas y las columnas, y cuando no es nulo, reemplaza por |y _respectivamente, luego pega ambas (sin dolor, gracias a la vectorización de R) y las salidas.

Casos de prueba:

> m=matrix(c(0,10,20,30,40,50,60,70,80,90,0,0,10,10,20,20,30,30,40,40,0,0,0,10,10,10,20,20,20,30,0,0,0,0,10,10,10,10,20,20,0,0,0,0,0,10,10,10,10,10,0,0,0,0,0,0,10,10,10,10,0,0,0,0,0,0,0,10,10,10,0,0,0,0,0,0,0,0,10,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0),byrow=T,ncol=10)
> f(m)
  |_|_|_|_|_|_|_|_|_
    |_  |_ _|_ _|_ _
      |_    |_ _  |_
        |_      |_ _
          |_        
            |_      
              |_    
                |_  
                  |_

> m=matrix(c(5,5,5,5,5,5,5,5,5,5,5,5,10,10,10,10,10,10,10,10,10,5,5,10,15,15,15,15,15,15,15,10,5,5,10,15,20,20,20,20,20,15,10,5,5,10,15,20,25,25,25,20,15,10,5,5,10,15,20,25,30,25,20,15,10,5,5,10,15,20,25,25,25,20,15,10,5,5,10,15,20,20,20,20,20,15,10,5,5,10,15,15,15,15,15,15,15,10,5,5,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,5,5),byrow=T,ncol=11)
> f(m)
   _ _ _ _ _ _ _ _ _  
  |                 | 
  |    _ _ _ _ _    | 
  |   |         |   | 
  |   |    _    |   | 
  |   |   |_|   |   | 
  |   |         |   | 
  |   |_ _ _ _ _|   | 
  |                 | 
  |_ _ _ _ _ _ _ _ _| 
plannapus
fuente
0

Perl 5 , 130 126 bytes

124 bytes de código + 2 para -apbanderas

push@a,[map 0|$_/10,@F]}{map{say map{($a[$r+1][$c]-$_&&$r<$#a?'_':$").($a[$r][++$c]-$_&&$c<@{$a[0]}?'|':$")}@$_;$c=0;$r++}@a

Pruébalo en línea!

El formato de entrada es una cuadrícula 2D de números separados por espacios.

Explicación

Esto es de una iteración previa del código.

push@a,[map 0|$_/10,@F]     # read the input, divide it by 10, and store it in a 2-D array
}{                          # end the implicit while loop and start the final block
map{                        # repeat this for each line
  $_=($a[$r+1][$c]-$_&&$r<$#a?'_':$")       # set appropriate characters to output based
     .($a[$r][++$c]-$_&&$c<@{$a[0]}?'|':$") # on the given rules
  for@$_;                                   # repeat for each number on the line
  $c=0;$r++;                         # setup row and column counters for next iteration
  say@$_                             # output this line
}@a
Xcali
fuente