Combien de tours pouvez-vous voir?


29

Cette question est basée sur les tours de puzzle de placement de numéros (également connues sous le nom de gratte-ciel), que vous pouvez jouer en ligne . Votre objectif est de trouver une solution au puzzle et de déterminer les indices - le nombre de tours visibles le long de chaque ligne et colonne. C'est le golf de code, donc le moins d'octets gagne.

Fonctionnement des tours

La solution à un casse - tête Towers est un carré latin - une n*ngrille dans laquelle chaque ligne et colonne contient une permutation des nombres 1par n. Un exemple pour n=5est:

4 3 5 2 1 
5 4 1 3 2 
1 5 2 4 3 
2 1 3 5 4 
3 2 4 1 5 

Chaque ligne et colonne est étiquetée avec un indice à chaque extrémité comme:

       2 3 1 4 5    
       v v v v v

 2 >   4 3 5 2 1   < 3
 1 >   5 4 1 3 2   < 4
 2 >   1 5 2 4 3   < 3
 3 >   2 1 3 5 4   < 2
 3 >   3 2 4 1 5   < 1 

       ^ ^ ^ ^ ^
       2 2 2 2 1

Chaque indice est un nombre de 1à nqui vous indique le nombre de tours que vous "voyez" en regardant le long de la ligne / colonne de cette direction, si les nombres sont traités comme des tours de cette hauteur. Chaque tour bloque des tours plus courtes derrière elle. En d'autres termes, les tours que vous pouvez voir sont celles qui sont plus hautes que n'importe quelle tour avant elles.

Image de Conceptis Puzzles

Par exemple, regardons la première ligne.

 2 >   4 3 5 2 1   < 3

Il a un indice de 2gauche parce que vous pouvez voir le 4et le 5. Le 4bloque la 3vue et 5bloque tout le reste. De la droite, vous pouvez voir des 3tours: 1, 2et 5.

Exigences du programme

Écrivez un programme ou une fonction qui prend dans la grille des nombres et des sorties ou imprime les indices, dans le sens horaire à partir du coin supérieur gauche.

Contribution

Un n*ncarré latin avec 2<=n<=9.

Le format est flexible. Vous pouvez utiliser n'importe quelle structure de données qui représente une grille ou une liste contenant des nombres ou des caractères numériques. Vous pouvez avoir besoin d'un séparateur entre les lignes ou pas de séparateur du tout. Certaines possibilités sont une liste, une liste de listes, une matrice, une chaîne séparée par jeton comme

43521 54132 15243 21354 32415,

ou une chaîne sans espaces.

Vous n'êtes pas donné ndans le cadre de l'entrée.

Sortie

Retournez ou imprimez les indices en partant du coin supérieur gauche et dans le sens des aiguilles d'une montre. Donc, d'abord les indices supérieurs lisant vers la droite, puis les indices droits lisant vers le bas, puis les indices inférieurs lisant vers la gauche, les indices gauches lisant vers le haut.

Ce serait 23145 34321 12222 33212pour l'exemple précédent

       2 3 1 4 5    
       v v v v v

 2 >   4 3 5 2 1   < 3
 1 >   5 4 1 3 2   < 4
 2 >   1 5 2 4 3   < 3
 3 >   2 1 3 5 4   < 2
 3 >   3 2 4 1 5   < 1 

       ^ ^ ^ ^ ^
       2 2 2 2 1

Tout comme pour l'entrée, vous pouvez utiliser une liste, une chaîne ou toute structure ordonnée. Les quatre "groupes" peuvent être séparés ou non, dans une structure imbriquée ou plate. Mais, le format doit être le même pour chaque groupe.

Exemples de cas de test:

(Votre format d'entrée / sortie ne doit pas nécessairement être le même que ceux-ci.)

>> [[1 2] [2 1]]

[2 1]
[1 2]
[2 1]
[1 2]

>> [[3 1 2] [2 3 1] [1 2 3]]

[1 2 2]
[2 2 1]
[1 2 3]
[3 2 1]

>> [[4 3 5 2 1] [5 4 1 3 2] [1 5 2 4 3] [2 1 3 5 4] [3 2 4 1 5]]

[2 3 1 4 5]
[3 4 3 2 1]
[1 2 2 2 2]
[3 3 2 1 2]

>> [[2 6 4 1 3 7 5 8 9] [7 2 9 6 8 3 1 4 5] [5 9 7 4 6 1 8 2 3] [6 1 8 5 7 2 9 3 4] [1 5 3 9 2 6 4 7 8] [3 7 5 2 4 8 6 9 1] [8 3 1 7 9 4 2 5 6] [9 4 2 8 1 5 3 6 7] [4 8 6 3 5 9 7 1 2]]

[4 2 2 3 3 3 3 2 1]
[1 3 3 2 2 2 2 3 3]
[4 3 2 1 2 3 3 2 2]
[3 1 2 4 3 3 2 2 5]

Pour votre commodité, voici les mêmes cas de test dans un format de chaîne plate.

>> 1221

21
12
21
12

>> 312231123

122
221
123
321

>> 4352154132152432135432415

23145
34321
12222
33212

>> 264137589729683145597461823618572934153926478375248691831794256942815367486359712

422333321
133222233
432123322
312433225

Réponses:


22

APL 19

≢¨∪/⌈\(⍉⍪⌽⍪⊖∘⌽∘⍉⍪⊖)

(golfé un peu plus après la suggestion de ngn, merci)

Explication:

(⍉⍪⌽⍪⊖∘⌽∘⍉⍪⊖)  rotates matrix 4 times appending results
⌈\ gets maximums for each row up to current column (example: 4 2 3 5 1 gives 4 4 4 5 5)
≢¨∪/ counts unique elements for each row

Essayez-le sur tryapl.org


1
Vous pouvez éviter d'ajouter 1:≢¨∪¨↓⌈\(⍉⍪⌽⍪⍉∘⌽∘⊖⍪⊖)
ngn

@ngn vous avez raison, merci! J'ai également appliqué ∪ / so 1 char de moins :)
Moris Zucca

Wow - c'est le genre de défi qu'APL excelle.
isaacg

12

Python 2, 115 octets

def T(m):o=[];exec'm=zip(*m)[::-1]\nfor r in m[::-1]:\n n=k=0\n for x in r:k+=x>n;n=max(x,n)\n o+=[k]\n'*4;return o

Il y a énormément de listes inversées en cours.

Prend l'entrée comme une liste imbriquée (par exemple, appelez avec T([[4,3,5,2,1],[5,4,1,3,2],[1,5,2,4,3],[2,1,3,5,4],[3,2,4,1,5]])). La sortie est une seule liste plate.

Non golfé:

def T(m):
 o=[]
 for _ in [0]*4:
  m=zip(*m)[::-1]
  for r in m[::-1]:
   n=k=0
   for x in r:k+=x>n;n=max(x,n)
   o+=[k]
 return o

Variante 115:

def T(m):o=[];exec'm=zip(*m)[::-1];o+=[len(set([max(r[:i+1])for i in range(len(r))]))for r in m[::-1]];'*4;return o

Je ne sais pas pourquoi cela fonctionne avec une compréhension de liste, mais jette un NameErroravec une compréhension d'ensemble ...

Un peu trop long, mais si quelqu'un est intéressé - oui, il est possible de le ramener à un lambda!

T=lambda m:[len({max(r[:i+1])for i in range(len(r))})for k in[1,2,3,4]for r in eval("zip(*"*k+"m"+")[::-1]"*k)[::-1]]

Pyth , 25 octets

V4=Q_CQ~Yml{meS<dhkUd_Q)Y

Port Pyth obligatoire.

Entrez la liste via STDIN, par exemple [[4, 3, 5, 2, 1], [5, 4, 1, 3, 2], [1, 5, 2, 4, 3], [2, 1, 3, 5, 4], [3, 2, 4, 1, 5]].

Essayez-le en ligne ... c'est ce que je dirais mais malheureusement, pour des raisons de sécurité, l'interpréteur en ligne interdit l'utilisation d'eval sur des crochets imbriqués. Essayez JcQ5V4=J_CJ~Yml{meS<dhkUd_J)Yplutôt le code de contournement et saisissez-le comme une liste aplatie comme [4, 3, 5, 2, 1, 5, 4, 1, 3, 2, 1, 5, 2, 4, 3, 2, 1, 3, 5, 4, 3, 2, 4, 1, 5].

(Merci à @isaacg qui a aidé à jouer au golf quelques octets)


Un couple de golfs Pyth: <et >sont les opérateurs de tranche unilatérale, ils :d0hkpeuvent donc être transformés en <dhk. Usur les entrées de collecte est identique à Ul, donc Uldpeut être transformé en Ud.
isaacg

@isaacg Merci - on dirait que mon Pyth a besoin d'être mis à jour. Le document que j'ai est obsolète.
Sp3000

11

CJam, 29 27 octets

q~{z_{[{1$e>}*]_&,}%pW%}4*;

Entrée comme

[[4 3 5 2 1] [5 4 1 3 2] [1 5 2 4 3] [2 1 3 5 4] [3 2 4 1 5]]

Sortie comme

[2 3 1 4 5]
[3 4 3 2 1]
[1 2 2 2 2]
[3 3 2 1 2]

Comment ça marche

L'idée de base est de faire travailler le code le long des lignes et de faire pivoter la grille dans le sens antihoraire 4 fois. Pour compter les tours, j'élève chaque tour dans la mesure où cela ne fait pas de "différence visuelle" (c'est-à-dire, ne la changez pas si elle est visible, ou ne la tirez pas à la même hauteur de la tour devant il), puis je compte des hauteurs distinctes.

q~                          "Read and evaluate the input.";
  {                    }4*  "Four times...";
   z                        "Transpose the grid.";
    _                       "Duplicate.";
     {            }%        "Map this block onto each row.";
      [       ]             "Collect into an array.";
       {    }*              "Fold this block onto the row.";
        1$                  "Copy the second-to-topmost element.":
          e>                "Take the maximum of the top two stack elements.";
                            "This fold replaces each element in the row by the
                             maximum of the numbers up to that element. So e.g.
                             [2 1 3 5 4] becomes [2 2 3 5 5].";
               _&,          "Count unique elements. This is how many towers you see.";
                    p       "Print array of results.";
                     W%     "Reverse the rows for the next run. Together with the transpose at
                             the start this rotates the grid counter-clockwise.";
                          ; "Get rid of the grid so that it isn't printed at the end.";


5

J, 35 caractères

(+/@((>./={:)\)"2@(|.@|:^:(<4)@|:))

Exemple:

   t=.4 3 5 2 1,. 5 4 1 3 2,. 1 5 2 4 3,. 2 1 3 5 4,. 3 2 4 1 5
   (+/@((>./={:)\)"2@(|.@|:^:(<4)@|:)) t
2 3 1 4 5
3 4 3 2 1
1 2 2 2 2
3 3 2 1 2

Essayez-le ici.


5

Haskell, 113

import Data.List
f(x:s)=1+f[r|r<-s,r>x]
f _=0
r=reverse
t=transpose
(?)=map
l s=[f?t s,(f.r)?s,r$(f.r)?t s,r$f?s]

4

Mathematica, 230,120,116,113 110 octets

f=(t=Table;a=#;s=Length@a;t[v=t[c=m=0;t[h=a[[y,x]];If[h>m,c++;m=h],{y,s}];c,{x,s}];a=Thread@Reverse@a;v,{4}])&

Usage:

f[{
  {4, 3, 5, 2, 1},
  {5, 4, 1, 3, 2},
  {1, 5, 2, 4, 3},
  {2, 1, 3, 5, 4},
  {3, 2, 4, 1, 5}
}]

{{2, 3, 1, 4, 5}, {3, 4, 3, 2, 1}, {1, 2, 2, 2, 2}, {3, 3, 2, 1, 2}}

a[[y]][[x]]est a[[y,x]]. Et l'utilisation Arraypourrait être plus courte que Table.
Martin Ender

4

JavaScript, 335 264 256 213

T=I=>((n,O)=>(S=i=>i--&&O.push([])+S(i)+(R=(j,a,x)=>j--&&R(j,0,0)+(C=k=>k--&&((!(a>>(b=I[(F=[f=>n-k-1,f=>j,f=>k,f=>n-j-1])[i]()][F[i+1&3]()])))&&++x+(a=1<<b))+C(k))(n)+O[i].push(x))(n,0,0))(4)&&O)(I.length,[],[])

Évaluez dans la console JavaScript du navigateur (j'ai utilisé Firefox 34.0, ne semble pas fonctionner dans Chrome 39 ??) Testez avec:

JSON.stringify(T([[4, 3, 5, 2, 1], [5, 4, 1, 3, 2], [1, 5, 2, 4, 3], [2, 1, 3, 5, 4], [3, 2, 4, 1, 5]]));

Voici l'incarnation actuelle du code non golfé - il devient plus difficile à suivre:

function countVisibleTowers(input) {
  return ((n, out) =>
      (sideRecurse = i =>
          i-- &&
          out.push([]) +
          sideRecurse(i) +
          (rowRecurse = (j, a, x) =>
              j-- &&
              rowRecurse(j, 0, 0) +
              (columnRecurse = k =>
                  k-- &&
                  ((!(a >> (b = input[
                                        (offsetFtn = [
                                            f => n - k - 1,   // col negative
                                            f => j,           // row positive
                                            f => k,           // col positive
                                            f => n - j - 1    // row negative
                                        ])[i]()
                                     ]
                                     [
                                        offsetFtn[i + 1 & 3]()
                                     ]))) &&
                  ++x +
                  (a = 1 << b)) +
                  columnRecurse(k)
              )(n) +
              out[i].push(x)
          )(n, 0, 0)
      )(4) && out
  )(input.length, [], [])
}

Je n'ai intentionnellement regardé aucune des autres réponses, je voulais voir si je pouvais trouver quelque chose moi-même. Mon approche consistait à aplatir les tableaux d'entrée en un tableau unidimensionnel et à précalculer les décalages vers les lignes dans les quatre directions. Ensuite, j'ai utilisé shift right pour tester si la prochaine tour était fausse et si c'était le cas, puis incrémenter le compteur pour chaque ligne.

J'espère qu'il existe de nombreuses façons d'améliorer cela, peut-être pas de précalculer les décalages, mais plutôt d'utiliser une sorte de débordement / modulo sur le tableau d'entrée 1D? Et peut-être combiner mes boucles, devenir plus fonctionnel, dédupliquer.

Toute suggestion serait appréciée!

Mise à jour # 1 : Progrès, nous avons la technologie! J'ai pu me débarrasser des décalages précalculés et les faire en ligne avec des opérateurs ternaires enchaînés. J'ai également pu me débarrasser de mon instruction if et convertir les boucles for en whiles.

Mise à jour # 2 : C'est assez frustrant; pas de pizza pour moi. Je pensais que devenir fonctionnel et utiliser la récursion raserait de nombreux octets, mais mes premiers essais ont fini par être plus gros de 100 caractères! En désespoir de cause, je suis allé à fond sur l'utilisation des fonctions de flèche de graisse ES6 pour vraiment le réduire. Ensuite, je me suis mis à remplacer les opérateurs booléens par des opérateurs arithmétiques et à supprimer les parens, les points-virgules et les espaces partout où je pouvais. J'ai même arrêté de déclarer mes vars et pollué l'espace de noms global avec mes symboles locaux. Sale, sale. Après tout cet effort, j'ai battu mon score de mise à jour # 1 par un énorme 8 caractères, jusqu'à 256. Blargh!

Si j'appliquais les mêmes optimisations impitoyables et astuces ES6 à ma fonction de mise à jour # 1, je battrais ce score d'un mile. Je peux faire une mise à jour # 3 juste pour voir à quoi cela ressemblerait.

Mise à jour # 3 : Il s'avère que l'approche récursive de la grosse flèche avait beaucoup plus de vie, j'avais juste besoin de travailler directement avec l'entrée bidimensionnelle plutôt que de l'aplatir et de mieux exploiter les portées de fermeture. J'ai réécrit les calculs de décalage du tableau interne deux fois et j'ai obtenu le même score, donc cette approche est peut-être proche d'être minée!


3

Java, uniquement 352 350 325 octets ...

class S{public static void main(String[]a){int n=a.length,i=0,j,k,b,c;int[][]d=new int[n][n];for(;i<n;i++)for(j=0;j<n;)d[i][j]=a[i].charAt(j++);for(i=0;i<4;i++){int[][]e=new int[n][n];for(k=0;k<n;k++)for(j=0;j<n;)e[n-j-1][k]=d[k][j++];d=e;for(j=n;j-->(k=c=b=0);System.out.print(c))for(;k<n;k++)b=d[j][k]>b?d[j][k]+0*c++:b;}}}

Entrée comme 43521 54132 15243 21354 32415

Sortie comme: 23145343211222233212

Dentelé:

class S{
    public static void main(String[]a){
        int n=a.length,i=0,j,k,b,c;
        int[][]d=new int[n][n];
        for(;i<n;i++)
            for(j=0;j<n;)d[i][j]=a[i].charAt(j++);
        for(i=0;i<4;i++){
            int[][]e=new int[n][n];
            for(k=0;k<n;k++)
                for(j=0;j<n;)e[n-j-1][k]=d[k][j++];
            d=e;
            for(j=n;j-->(k=c=b=0);System.out.print(c))
                for(;k<n;k++)b=d[j][k]>b?d[j][k]+0*c++:b;
        }
    }
}

Tous les conseils seraient grandement appréciés!


vous avez quelques espaces supplémentaires entre les forboucles
fier haskeller

@proud haskeller Merci!
TheNumberOne

Vous pouvez changer for(;i<n;i++)à for(;++i<n;)et initialiser ià -1. Ensuite, utilisez-les pour faire des choses. Vous pouvez également faire de même avec l'autre boucle.
fier haskeller

Vous pouvez utiliser a[i].charAt(j)-'0'au lieu d'une analyse explicite. Cela ne nécessite pas non plus de délimiteurs dans l'entrée (rend le format d'entrée plus semblable au format de sortie).
anatolyg

De plus, dans for-loops, vous pouvez toujours placer quelque chose d'utile dans la partie "incrément de boucle". Cela rend le code plus obscur et supprime un point-virgule. Par exemple: for(j=n;j-->0;System.out.print(c)).
anatolyg

1

Python 2 - 204 octets

def f(l):n=len(l);k=[l[c]for c in range(n)if l[c]>([0]+list(l))[c]];return f(k)if k!=l else n
r=lambda m:(l[::-1]for l in m)
m=input();z=zip(*m);n=0
for t in z,r(m),r(z),m:print map(f,t)[::1-(n>1)*2];n+=1

C'est probablement un golf vraiment médiocre. Je pensais que le problème était intéressant, alors j'ai décidé de le résoudre sans regarder la solution de quelqu'un d'autre. En tapant cette phrase, je n'ai pas encore examiné les réponses à cette question. Je ne serais pas surpris si quelqu'un d'autre a déjà fait un programme Python plus court;)

Exemple d'E / S

$ ./towers.py <<< '[[4,3,5,2,1],[5,4,1,3,2],[1,5,2,4,3],[2,1,3,5,4],[3,2,4,1,5]]'
[2, 3, 1, 4, 5]
[3, 4, 3, 2, 1]
[1, 2, 2, 2, 2]
[3, 3, 2, 1, 2]

Vous pouvez éventuellement inclure des espaces dans l'entrée. À peu près n'importe où, honnêtement. Tant que vous le pouvez eval(), cela fonctionnera.

Explication

La seule partie intéressante de ce programme est la première ligne. Il définit une fonction f(l)qui vous indique combien de tours peuvent être vues dans une rangée, et le reste du programme applique simplement cette fonction à chaque position possible.

Lorsqu'il est appelé, il trouve la longueur de let l'enregistre dans une variable n. Ensuite, il crée une nouvelle variable kavec cette compréhension de liste assez monstrueuse:

[l[c]for c in range(n)if l[c]>([0]+list(l))[c]]

Ce n'est pas trop mal quand vous le décomposez. Depuis n==len(l), tout ce qui précède ifreprésente juste l. Cependant, en utilisant ifnous pouvons supprimer certains éléments de la liste. Nous construisons une liste avec ([0]+list(l)), qui est juste " lavec un 0ajout au début" (ignorez l'appel à list(), ce n'est là que parce qu'il y a parfois lun générateur et nous devons nous assurer qu'il s'agit bien d'une liste ici). l[c]n'est mis dans la liste finale que s'il est supérieur à ([0]+list(l))[c]. Cela fait deux choses:

  • Puisqu'il y a un nouvel élément au début de la liste, l'index de chacun l[c]devient c+1. Nous comparons efficacement chaque élément à l'élément à gauche de celui-ci. Si c'est plus, c'est visible. Sinon, il est masqué et supprimé de la liste.
  • La première tour est toujours visible car rien ne peut la bloquer. Parce que nous mettons 0 au début, la première tour est toujours plus grande. (Si nous ne le faisions pas un [0]+non - sens et juste comparé l[c]à l[c-1], Python comparerait la première tour à la dernière (vous pouvez indexer dans une liste à partir de la fin avec -1, -2etc.), donc si la dernière tour était plus grand que la premier nous obtiendrions le mauvais résultat.

En fin de compte, lcontient un certain nombre de tours et kcontient chacune de celles qui ne sont pas plus courtes que son voisin immédiat à gauche. Si aucun d'entre eux ne l'était (par exemple pour f([1,2,3,4,5])), alors l == k. Nous savons qu'il n'y a plus rien à faire et à retourner n(la longueur de la liste). Si l != k, cela signifie qu'au moins une des tours a été supprimée cette fois-ci et il peut y avoir plus à faire. Donc, nous revenons f(k). Dieu, j'aime la récursivité. Fait intéressant, frécursive toujours un niveau plus profond que strictement "nécessaire". Lorsque la liste qui sera retournée est générée, la fonction n'a aucun moyen de le savoir au début.

Lorsque j'ai commencé à écrire cette explication, ce programme faisait 223 octets. En expliquant les choses, j'ai réalisé qu'il y avait des moyens de sauver des personnages, donc je suis content d'avoir tapé ça! Le plus grand exemple est celui qui f(l)a été implémenté à l'origine comme une boucle infinie qui a été rompue lorsque le calcul a été effectué, avant que je ne réalise que la récursivité fonctionnerait. Cela montre simplement que la première solution à laquelle vous pensez ne sera pas toujours la meilleure. :)


0

Matlab, (123) (119)

function r=m(h);p=[h rot90(h) rot90(h,2) rot90(h,3)];for i=2:size(p) p(i,:)=max(p(i,:),p(i-1,:));end;r=sum(diff(p)>0)+1

utilisé comme ceci:

m([
 4     3     5     2     1;
 5     4     1     3     2;
 1     5     2     4     3;
 2     1     3     5     4;
 3     2     4     1     5])

 [2 3 1 4 5 3 4 3 2 1 1 2 2 2 2 3 3 2 1 2]

C #, jusqu'à 354 ...

Approche différente de celle utilisée par TheBestOne.

using System;
using System.Linq;

class A
{
    static void Main(string[] h)
    {
        int m = (int)Math.Sqrt(h[0].Length),k=0;
        var x = h[0].Select(c => c - 48);
        var s = Enumerable.Range(0, m);
        for (; k < 4; k++)
        {
            (k%2 == 0 ? s : s.Reverse())
                .Select(j =>
                        (k > 0 && k < 3 ? x.Reverse() : x).Where((c, i) => (k % 2 == 0 ? i % m : i / m) == j)
                                                          .Aggregate(0, (p, c) =>
                                                                        c > p%10
                                                                            ? c + 10 + p/10*10
                                                                            : p, c => c/10))
                .ToList()
                .ForEach(Console.Write);
        }
    }
}

Il semble que votre ordinateur colle \nau lieu de nouvelles lignes, je viens de les remplacer par des espaces, donc le code s'exécute immédiatement lorsque quelqu'un le copie. Et je me suis permis de supprimer le dernier end(qui ferme la fonction, ce qui n'est pas nécessaire) qui enregistre 4 caractères supplémentaires, j'espère que c'était ok =)
flawr

Il semble que matlab n'était pas satisfait des espaces, alors je les ai changés en points-virgules. Bon point sur la fuite endcependant, thx :)
zabalajka
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.