Dessine mes contours

25

Étant donné une matrice rectangulaire d'élévations, dessinez ses contours.

Tâche

Deux éléments xet ysont au même niveau de contour si floor(x/10) == floor(y/10). Par exemple, 52et 58sont sur le même niveau de contour, mais 58et 64ne sont pas.

L'acte de dessiner des contours est défini comme suit: Pour chaque élément e, remplacez-le par une chaîne de deux caractères choisie comme suit:

  • le premier caractère est " "si l'élément ci e- dessous est au même niveau de contour que es'il n'y a pas d'élément en dessous eet "_"sinon
  • le deuxième caractère est " "si l'élément à droite de eest au même niveau de contour que es'il n'y a pas d'élément à droite de eet "|"autrement

Les éléments des lignes sont joints ensemble, puis les lignes sont jointes avec des retours à la ligne.

Exemple

Disons que l'entrée est [[5,20],[3,6]], visualisée comme

5 20
3 6

Nous regardons d'abord 5. Puisque se 3trouve au même niveau de contour que 5, le premier caractère est " ". Puisque 20n'est pas au même niveau de contour que 5, le deuxième caractère l'est "|".

Maintenant, nous regardons 20. Puisque 6n'est pas au même niveau de contour que 20, le premier caractère l'est "_". Puisqu'il n'y a aucun élément à droite de 20, le deuxième caractère est " ".

Maintenant, nous regardons 3. Puisqu'il n'y a aucun élément ci 3- dessous , le premier caractère est " ". Puisque 6est au même niveau de contour que 3, le deuxième caractère est " ".

Maintenant, nous regardons 6. Puisqu'il n'y a aucun élément ci 6- dessous , le premier caractère est " ". Puisqu'il n'y a aucun élément à droite de 6, le deuxième caractère est " ".

Sur la base de ces chaînes de deux caractères, nous effectuons des remplacements pour obtenir [[" |","_ "],[" "," "]]. En les joignant ensemble, nous obtenons une sortie de

 |_ 
    

Règles

  • La matrice d'entrée sera toujours rectangulaire et composée d'entiers positifs.
  • Les espaces de fin ou les sauts de ligne peuvent être de n'importe quelle quantité (y compris 0) et ne doivent en aucun cas être cohérents.
  • Vous n'avez pas à suivre le même algorithme tant que vous produisez les mêmes résultats.
  • Votre programme ou fonction peut générer une chaîne, une liste de chaînes séparées par des sauts de ligne ou l'équivalent.
  • C'est le , donc le code le plus court en octets gagne.

Cas de test

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
la source
1
Je ne commence même pas à lire ceci avant de réaliser à quel point ce sera cool
Christopher

Réponses:

6

Perl 6 , 135 octets (131 caractères)

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

Essayez-le en ligne!

Légèrement non golfé:

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

Explication : Tout d'abord, nous définissons une variable $n(ligne 2) et une fonction w(ligne 3). Cette fonction renvoie un espace si ses deux arguments sont à la même "élévation", et le contenu de la variable $nsinon. Au lieu de diviser par 10 et parquets, nous abusons du fait que les nombres entiers sont Cool(peuvent être traités comme des chaînes) et utilisés choppour supprimer le dernier caractère (= chiffre). Ensuite, nous les soustrayons calmement, les forçant à nouveau en nombres :—).

Après cela (ligne 4), nous créons une fonction qqui prend une liste et retourne cette liste avec le premier élément supprimé et le dernier élément dupliqué.

Sur les 3 lignes suivantes, nous allons créer 2 matrices supplémentaires à partir de la matrice d'entrée: la première a la première ligne manquante et la dernière ligne dupliquée (c'est juste .&q- en utilisant .&, vous pouvez appeler une fonction sur n'importe quoi comme si elle était une méthode - la chose devant le point est alors le premier argument), l'autre a la première colonne manquante et la dernière colonne dupliquée (c'est .map(*.&q)).

Tout d'abord (ligne 4), nous prenons la matrice d'origine $_, la "superposons" avec la matrice "lignes décalées" et utilisons la fonction wcomme un opérateur binaire (c'est ça [&w]) sur les éléments correspondants. Celui-là met un _partout où les éléments correspondants sont sur les différentes élévations, et un autre. On obtient donc la moitié du résultat (uniquement les "premiers caractères").

À la ligne 6, nous faisons la même chose, mais nous passons d'abord $nà |, et nous «superposons» maintenant la matrice d'origine avec la matrice à colonnes décalées. Le résultat a une altitude |différente et la même. Ce sont les "seconds caractères".

Maintenant, nous les combinons simplement. On zippe les tableaux avec un zip avec un enchaînement (ouais ...), ce qui se traduit par une matrice de la forme originale dont chaque élément est les 2 éléments correspondants des "demi-solutions" concaténées. Enfin, nous cartographions simplement cette matrice (qui est en réalité une liste de listes). Chacune de ces listes est aplatie puis mise à jour say(imprimée avec une nouvelle ligne). Puisqu'il saypeut prendre n'importe quel nombre d'arguments et qu'il les imprime tous sans séparateurs, faisant la nouvelle ligne uniquement à la fin, nous obtenons l'image souhaitée sur stdout. (Et le bloc renvoie une liste de Trues (chacun en sayretourne un True), mais peu importe.)

Ramillies
la source
+1 pourbut who cares
HyperNeutrino
5

Gelée ,  25 23  22 octets

-1 octet grâce aux miles ( Ivectorise)

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

Un programme complet imprimant le résultat. En tant que lien monadique, il prend une liste de listes de nombres, les élévations et renvoie une liste de listes, mais ces "lignes" sont constituées de listes de "paires" de deux caractères - si cela est correct, 1 octet peut être enregistré en supprimant Y.

Essayez-le en ligne!

Comment?

:⁵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
la source
grr 3 octets. +1 mais j'essaierai de vous surpasser;)
HyperNeutrino
Solution indépendante - vient de voir la vôtre est très similaire! vous sauve un de suite ...
Jonathan Allan
Vous pouvez enregistrer un octet en utilisant chacun sur la jointure dans l'assistant :⁵I;€0ao⁶au lieu du lien principalZç”_Zż"ç”|$Y
miles
@miles Oh wow, ça marche? Merci! J'imaginais que je Ine vectoriserais pas comme ça.
Jonathan Allan
Ouais Ivectorise en profondeur 1, et les deux aet ovectorise en profondeur 0
miles
3

Python 2 , 199 186 157 155 octets

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])

Essayez-le en ligne!

Chas Brown
la source
3

Gelée , 24 octets

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

Essayez-le en ligne!

Explication

:⁵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 octets grâce à Jonathan Allan

HyperNeutrino
la source
Votre solution peut en fait supprimer le Y- elle renverra une liste de listes de caractères, ce qui, je pense, est OK (alors que le mien a des paires à l'intérieur des "lignes").
Jonathan Allan
@JonathanAllan oh ouais vrai ... merci!
HyperNeutrino
2

Python 2 , 226 octets

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:]))

Essayez-le en ligne!

Ouf, c'était un peu compliqué de trouver la logique. Je vois maintenant Hyper Neutrino ninja'd avec une réponse plus courte mais j'ai consacré trop de temps à cela pour ne pas le publier. : P

De plus, je peux simplement dire que c'est une excellente façon de créer de l'art ASCII. Excusez-moi pendant que j'en fais encore plus.

totalement humain
la source
> ninja'd: mec ça fait 45 minutes
HyperNeutrino
Ouais, je n'ai pas regardé les réponses ...: P
totalement humain
Vous pouvez enregistrer 4 octets en définissant une variable pour enumerateau lieu d'utiliser deux fois le nom complet.
Jonathan Frech
218 octets en supprimant le premier enumerate(obs, j'ai dû supprimer certaines entrées pour pouvoir le lier ici)
Felipe Nardi Batista
2

J, 58 octets

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

Essayez-le en ligne!

Une fonction anonyme qui prend une matrice et sort les contours.

Beaucoup de choses à améliorer ici. Je n'ai pas eu le temps d'essayer tous les cas de test, alors faites-moi savoir s'il y a des problèmes. J'essaierai de jouer au golf plus et expliquerai plus tard.

(Rapide) Explication

Fonction d'assistance: indexe dans une chaîne de longueur 2 selon que le premier élément d'un tableau de 2 longueurs est égal au second. S'il est égal, il indexe dans l'élément zéro, s'il est inégal, il indexe dans le premier. Un tableau de 1 longueur indexe toujours l'élément zéro de la chaîne.

f=.{~0==/@]

Fonction principale

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

1:+<.@%&10 planchers chaque élément divisé par 10 et ajoute 1 (donc nous n'obtiendrons jamais 0 - c'est important pour la fonction d'assistance).

2 2((' _'f{."1),' |'f{.);.3coupe la matrice en 2 x 2 segments si elle le peut (sinon cela donnera un segment 2 x 1, 1 x 2 ou 1 x 1 près des bords) et applique la fonction qui utilise fpour comparer l'élément supérieur gauche au sommet à droite et l'élément en haut à gauche en bas à gauche.

(,/"2)aplatit le résultat dans la forme souhaitée. Je pense vraiment que je devrais pouvoir éviter d'avoir à utiliser cela (et beaucoup d'autres choses, mais je m'égare).

cole
la source
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`

\nreprésente le caractère de nouvelle ligne littéral. Edit: sauvé 2 octets grâce à @ 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
la source
Vous pouvez transformer les (a[i] || [])[j]constructions en(a[i] || 0)[j]
Bálint
En outre, dans le dernier, join`\n`vous pouvez supprimer la \npièce et la remplacer par une nouvelle ligne réelle
Bálint
114 octets: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, j'oublie toujours de faire cette \npartie; Je teste dans un REPL pour que les nouvelles lignes littérales gênent.
Neil du
@ Bálint Mais votre dernière suggestion échoue pour l'exemple original, que j'ai ajouté à la liste des sorties.
Neil
1

Proton , 202 octets

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)])))

Essayez-le en ligne!

-2 octets grâce à Jonathan Frech
-15 octets en passant à Proton au lieu de Python 2

HyperNeutrino
la source
Vous pouvez enregistrer deux octets en remplaçant lenavec Let la définition L=len;.
Jonathan Frech
1

Java 8, 200 170 169 octets

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;}

Explication:

Essayez-le ici.

Notez que la division entière en Java est automatiquement mise en plan.

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
la source
1

R, 159 octets

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),,"")}

Avec des nouvelles lignes et des indentations:

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),,"")
    }

Est-ce que la division entière de la matrice, mesure les différences entre les lignes et les colonnes, et lorsqu'elle n'est pas nulle, remplace par |et _respectivement, puis colle à la fois (indolore, grâce à la vectorisation de R) et les sorties.

Cas de test:

> 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
la source
0

Perl 5 , 130 126 octets

124 octets de code + 2 pour les -apdrapeaux

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

Essayez-le en ligne!

Le format d'entrée est une grille 2D de nombres séparés par des espaces.

Explication

Ceci provient d'une précédente itération du code.

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
la source