C'est un défi sur Internet que Palantir Technologies a demandé dans leurs interviews .
Un groupe d'agriculteurs a des données d'altitude, et nous allons les aider à comprendre comment les précipitations coulent sur leurs terres agricoles. Nous représenterons la terre comme un tableau bidimensionnel d'altitudes et utiliserons le modèle suivant, basé sur l'idée que l'eau s'écoule vers le bas:
Si les quatre cellules voisines d'une cellule ont toutes des altitudes plus élevées, nous appelons cette cellule un puits; l'eau s'accumule dans les éviers. Sinon, l'eau coulera vers la cellule voisine avec l'altitude la plus basse. Si une cellule n'est pas un puits, vous pouvez supposer qu'elle a un voisin le plus bas unique et que ce voisin sera inférieur à la cellule.
Les cellules qui s'écoulent dans le même évier - directement ou indirectement - feraient partie du même bassin.
Votre défi est de partitionner la carte en bassins. En particulier, étant donné une carte des élévations, votre code doit partitionner la carte en bassins et afficher les tailles des bassins, par ordre décroissant.
Supposons que les cartes d'élévation sont carrées. L'entrée commencera par une ligne avec un entier, S, la hauteur (et la largeur) de la carte. Les S lignes suivantes contiendront chacune une ligne de la carte, chacune avec S entiers - les élévations des S cellules de la ligne. Certains agriculteurs ont de petites parcelles de terrain comme les exemples ci-dessous, tandis que d'autres ont des parcelles plus grandes. Cependant, en aucun cas, un agriculteur ne disposera d'une parcelle de terrain supérieure à S = 5000.
Votre code doit afficher une liste des tailles de bassin séparées par des espaces, par ordre décroissant. (Les espaces de fin sont ignorés.)
Voici quelques exemples.
Contribution:
3
1 5 2
2 4 7
3 6 9
Production:
7 2
Les bassins, étiquetés avec A et B, sont:
A A B
A A B
A A A
Contribution:
1
10
Production:
1
Il n'y a qu'un seul bassin dans ce cas.
Contribution:
5
1 0 2 5 8
2 3 4 7 9
3 5 7 8 9
1 2 5 4 2
3 3 5 2 1
Production:
11 7 7
Les bassins, étiquetés avec A, B et C, sont:
A A A A A
A A A A A
B B A C C
B B B C C
B B C C C
Contribution:
4
0 2 1 3
2 1 0 4
3 3 3 3
5 5 2 1
Production:
7 5 4
Les bassins, étiquetés avec A, B et C, sont:
A A B B
A B B B
A B B C
A C C C
la source
Réponses:
Mathematica
La liste des tailles de bassin peut être obtenue par
où
m
sont les données d'entrée données. Pour afficher une matrice comme celles de la question, on peut remplacer// Reverse@Sort@Part[Tally[Flatten@#], All, 2] &
par/. {1 -> "A", 2 -> "B", 3 -> "C"} // MatrixForm
ou on peut l'afficher comme une image à la place en utilisant//ImageAdjust//Image
.la source
JavaScript - 673
707730751e=[],g=[],h=[],m=[],q=[];function r(){a=s,b=t;function d(d,A){n=a+d,p=b+A;c>e[n][p]&&(u=!1,v>e[n][p]&&(v=e[n][p],w=n,k=p))}c=e[a][b],u=!0,v=c,w=a,k=b;0!=a&&d(-1,0);a!=l&&d(1,0);0!=b&&d(0,-1);b!=l&&d(0,1);g[a][b]=w;h[a][b]=k;return u}function x(a,b,d){function c(a,b,c,k){g[a+b][c+k]==a&&h[a+b][c+k]==c&&(d=x(a+b,c+k,d))}d++;0!=a&&c(a,-1,b,0);a!=l&&c(a,1,b,0);0!=b&&c(a,0,b,-1);b!=l&&c(a,0,b,1);return d}y=$EXEC('cat "'+$ARG[0]+'"').split("\n");l=y[0]-1;for(z=-1;z++<l;)e[z]=y[z+1].split(" "),g[z]=[],h[z]=[];for(s=-1;s++<l;)for(t=-1;t++<l;)r()&&m.push([s,t]);for(z=m.length-1;0<=z;--z)s=m[z][0],t=m[z][1],q.push(x(s,t,0));print(q.sort(function(a,b){return b-a}).join(" "));
Résultats des tests (avec Nashorn):
Il y aurait probablement des problèmes de pile pour les cartes de taille 5000 (mais c'est un détail d'implémentation :).
La source non minimisée dans toute sa grossièreté:
J'ai obtenu de meilleurs résultats de minimisation en divisant les objets élément en tableaux séparés, en globalisant partout où cela était possible et en adoptant les effets secondaires. NSFW.
Les effets de la minimisation du code:
J'aurais pu atteindre près de 700 octets sans éditer le code minimisé si j'avais voulu modifier la source d'origine. Mais je ne l'ai pas fait car je pense que le laisser tel quel donne une vue intéressante du point de départ.
la source
var e=[],g=[],h=[],l,m=[],q=[]
àe=g=h=l=m=q=[]
. Vous pouvez probablement également vous débarrasser d'autres utilisations duvar
mot - clé si vous n'observez aucune variable globale.Python: 276
306 365octetsCeci est ma première tentative de golf. Les suggestions sont appréciées!
edit: les importations et la fermeture des fichiers prennent trop de caractères! Il en va de même pour le stockage de fichiers dans des variables et la compréhension de listes imbriquées.
entièrement commenté (2130 octets ...)
la source
open('a').read()
Je pense que vous devriez pouvoir le faire .JavaScript (ECMAScript 6) - 226 caractères
Explication
Version précédente - 286 caractères
Suppose que l'entrée est dans une variable
S
;Explication
Tester
Les sorties:
[7, 2]
Les sorties:
[11, 7, 7]
Les sorties:
[5, 7, 4]
la source
Julia, 315
Juste une fonction récursive qui détermine que la cellule actuelle est un puits ou trouve le drain, puis appelez cela sur chaque ensemble d'indices. Je n'ai pas pris la peine de faire la partie entrée car je n'allais pas gagner de toute façon, et cette partie n'est pas amusante.
la source
Haskell, 271
286Peut-être encore du code à jouer ici.
Explication
Idée de base: pour chaque cellule (i, j), trouvez la cellule la plus basse du "voisinage". Cela donne un graphique [ (i, j) → (mi, mj) ]. Si une cellule est la cellule la plus basse elle-même, alors (i, j) == (mi, mj) .
Ce graphique peut être itéré: Pour chaque a → b dans le graphique, remplacez-le par a → c où b → c est dans le graphique. Lorsque cette itération ne produit plus de modifications, chaque cellule du graphique pointe vers la cellule la plus basse vers laquelle elle ira.
Pour jouer au golf, plusieurs changements ont été apportés: Premièrement, les coordonnées sont représentées comme une liste de longueur 2, plutôt que comme une paire. Deuxièmement, une fois que les voisins ont été trouvés, les cellules sont représentées par leur indice dans un tableau linéaire des cellules, et non par des coordonnées 2D. Troisièmement, comme il y a n * n cellules, après n * n itérations, le graphique doit être stable.
Ungolf'd
la source
Rubis, 216
C'est une approche légèrement différente, qui n'appelle "flow" sur chaque carré qu'une seule fois (les performances dépendent de la performance d'Array :: index). Il va de l'élévation la plus élevée à la plus basse, vidant une cellule à la fois dans son voisin le plus bas et marquant la cellule comme terminée (en ajoutant 1 à l'élévation) lorsqu'elle est terminée.
Commenté et espacé:
Journal des modifications:
216 - meilleure façon de désélectionner les indices hors limites
221 - se révèle, "11" vient avant "2" ... revenir à
to_i
, mais économisez un peu d'espace sur notregets
es.224 - Pourquoi déclarer
s
quand même? Eteach
=>map
229 - Golf massif - Triez d'abord les élévations
s
(et supprimez ainsi lawhile
clause), utilisezmin_by
plutôt quesort_by{...}[0]
, ne vous embêtez pasto_i
pour les élévations, utilisezflat_map
et réduisezselect{}
bloc271 - déplacement de la taille du bassin versant dans un nouveau tableau et utilisation de sort_by
315 - déplacé les résultats vers un tableau qui offrait toutes sortes d'avantages et une liste d'index de voisin raccourcie. a également gagné un caractère dans l'indice lambda.
355 - premier commit
la source
Python -
470 447 445 393 392 378 376 375 374369 octetsJe ne peux pas m'arrêter!
Pas une solution gagnante, mais j'ai eu beaucoup de plaisir à la créer. Cette version ne suppose pas que l'entrée soit stockée n'importe où et la lit à partir de stdin. Profondeur de récursivité maximale = distance la plus longue d'un point à son puits.
Je n'ai pas le temps de l'expliquer aujourd'hui, mais voici le code non golfé:Il est en fait assez différent du code d'origine. J'ai lu les lignes S de stdin, split, mappé en pouces et aplati les listes pour obtenir le champ aplati. Ensuite, je passe en revue toutes les tuiles (permettez-moi de les appeler des tuiles) une fois. La fonction de flux vérifie les tuiles voisines et sélectionne celle avec la plus petite valeur. Si elle est plus petite que la valeur de la tuile actuelle, déplacez-vous dessus et récursivement. Sinon, la tuile actuelle est un évier et un nouveau bassin est créé. La valeur de retour de la récursivité est l'id du bassin.
la source
JavaScript (ES6) 190
203Éditer Un peu plus ES6ish (1 an plus tard ...)
Définir une fonction avec des lignes d'entrée sous forme de chaîne, y compris les sauts de ligne, renvoyer la sortie sous forme de chaîne avec des espaces de fin
la source
Perl 6,
419404Ajout de nouvelles lignes pour plus de clarté. Vous pouvez les retirer en toute sécurité.
Ancienne solution:
Et pourtant, je suis battu par les solutions Python et JavaScript.
la source