Quelle est la variété de ma course d'obstacles?


21

Contexte

J'ai construit un parcours d'obstacles simple en plaçant des boîtes dans une pièce rectangulaire. Maintenant, je veux compter le nombre de façons essentiellement différentes de le résoudre. J'ai besoin que vous m'écriviez un programme pour ça.

Contribution

Votre entrée est un tableau rectangulaire non vide de caractères .#. Les points .sont des espaces vides et les #obstacles sont.

Un chemin à travers la course d'obstacles commence dans le coin supérieur gauche et se termine dans le coin inférieur droit, et ne va que vers la droite ou vers le bas. De plus, un chemin valide ne peut pas traverser un obstacle. Voici quelques exemples dessinés avec des +caractères:

Valid path  Invalid path  Invalid path  Invalid path
++........   ++........    +++++.....    ..+.......
.++++++#..   .+.....#..    ....+++#++    ..++...#..
......+#..   .+.++++#..    .......#.+    ...+++.#..
....#.++++   .+++#.++++    ....#....+    ....#+....

Deux chemins sont essentiellement similaires 1 si l'un peut être transformé en l'autre en se déplaçant un +à la fois. Les chemins intermédiaires doivent également être valides, vous ne pouvez donc pas plier un chemin au-dessus d'un obstacle. Par exemple, les deux premiers chemins ici sont essentiellement similaires, mais le troisième est essentiellement différent d'eux, car il ne peut pas être déplacé sur les deux obstacles:

++........   +.........   +++++++++.
.+++++.#..   ++.....#..   .......#+.
.....+.#..   .++++++#..   .......#++
....#+++++   ....#.++++   ....#....+

Production

Votre résultat est le nombre de chemins essentiellement différents à travers le parcours du combattant. En d'autres termes, si tous les chemins valides sont divisés en classes de chemins essentiellement similaires, la sortie est le nombre de classes. Notez que ce nombre peut être 0 s'il n'y a pas de chemins valides.

Règles et notation

Vous pouvez écrire un programme complet ou une fonction. Le nombre d'octets le plus bas l'emporte et les failles standard sont interdites. Il n'y a pas de limites de temps, sauf que vous devez évaluer votre programme sur chaque cas de test avant de le soumettre.

Cas de test

....
....
.... => 1

...#
....
...# => 0

#..#
..#.
.... => 0

......
......
..##..
......
...... => 2

......
...#..
......
..#...
#..... => 3

......
..#...
......
....#.
#..... => 4

.......
##.....
....###
...#...
..##.#.
#....#.
..#.... => 0

......#.
..##....
...#....
.......#
....#...
.##...#.
....#...
##...... => 7

.........
.#.#.#.#.
.........
#.#...#.#
.........
.#.#.#.#.
......... => 17

..........
.#........
..........
.....#....
#.........
........#.
......#...
.......... => 10

.........
.#.......
.........
...#.....
.........
.....#...
.........
.......#.
......... => 16

1 Le terme technique correct est "homotopique" .


1
Qu'entendez-vous par « déplacer un +à la fois »? Est-ce à dire que des chemins essentiellement similaires doivent avoir la même longueur?
Peter Taylor

3
@PeterTaylor Tous les chemins ont la même longueur, car ils ne peuvent que descendre et à droite. Par «déplacer un +», j'entends essentiellement qu'un coin du chemin est inversé dans un coin de la direction opposée.
Zgarb

1
@Peter: Puisque vous ne pouvez aller qu'à droite ou en bas, tous les chemins ont la même longueur.
Deusovi

Réponses:


8

Escargots , 53 49 octets

A^
\.+d!{.l\.+a3(.|~c!~}\.+r!(.u\.+e(.|~},\.,=~d~

Pour une fois, je n'ai pas eu à utiliser t, la redoutable instruction de téléportation. En conséquence, les cas de test se terminent instantanément au lieu de prendre des éons.

Non golfé:

A^
r\.+
{
    d\.+
    !{ r\.u \.+ a3 (.|~)}
    r\.+
    !{ d\.l \.+ a3 (.|~)}
},
d\.,
!(dr .)

Les options A^signifient commencer dans le coin supérieur gauche et compter tous les chemins correspondants. L'idée principale est de vérifier une condition de canonicité pour les chemins. Honnêtement, je ne m'attendais pas à ce que cela fonctionne, mais il a cloué les cas de test, alors ... Ce qu'il essaie de vérifier, c'est que, dans le chemin actuel, l'itinéraire le plus gourmand a été sélectionné, c'est-à-dire aller le plus de fois possible , descendre autant de fois que possible, etc. sans franchir d'obstacles. Cela se fait en vérifiant, après avoir bougé 1 fois ou plus à droite puis 1 ou plusieurs fois vers le bas, que le carré suivant (qui doit être à droite) n'a pas pu être atteint en allant encore une fois à droite dans le segment droit précédent. La condition analogue est également vérifiée après un déplacement vers la droite puis vers le bas.


parler de la bonne langue pour le travail!
Pas que Charles

10

Python 2, 170 131 112 octets

def f(C,t=1):i="#".join(C).find("#")+1;return([]<C)*(i<1or(i<t
and f([r[i:]for r in C],t-i))+(i>1)*f(C[1:],i-1))

Une fonction, fprenant le parcours du combattant comme une liste de lignes et renvoyant le nombre de chemins essentiellement différents.

Explication

Le concept de base est le suivant: nous choisissons un certain obstacle, o , de telle sorte qu'il n'y ait pas d'autres obstacles dans la boîte délimitant o et le coin supérieur gauche.

+--+....
|..|....  
+--#<==== o
.....#..
.#......
........

Nous considérons ensuite les deux sous-cours à l'est et au sud de o . Nous ne considérons l'un de ces sous-cours que si o peut effectivement être traversé dans une direction qui y mène, c'est-à-dire traversé du nord pour se rendre à l'est, et traversé de l'ouest pour se rendre au sud. Nous résolvons le problème pour chacun des sous-cours sélectionnés et retournons la somme des résultats. Ces nombres correspondent au nombre de chemins essentiellement différents lors du croisement de o de gauche et de droite, respectivement, donc les deux ensembles de chemins résultants sont essentiellement différents. Puisqu'il n'y a aucun obstacle entre le point de départ et o, il existe un chemin entre le point de départ et tout point d'entrée dans chacune de ces régions, et tous ces chemins qui mènent au même point sont essentiellement similaires, d'où la somme ci-dessus est le nombre complet de chemins essentiellement différents dans l'ensemble du parcours.

                               A
_
........       ...|////      |....
........       ...|////      |....
...#....  -->  ...#////  -->  ....
.#....#.       .#..//#/       ..#.
........       ....////       ....

   |                           |
   v                           v
                  B
........       ___
........       .#....#.
___#....  -->  ........  -->   +
/#////#/       
////////       

Les choses sont légèrement compliquées par le fait que le parcours du combattant à lui seul ne transmet pas toutes les informations nécessaires. Par exemple, considérez le cours B dans le diagramme ci-dessus. Pris isolément, nous ne pouvons pas déterminer si chacun des obstacles peut être franchi par le nord. Si B était la route d'entrée, alors, puisque tous les chemins commencent dans le coin supérieur gauche, aucun obstacle n'aurait pu être traversé du nord, mais, puisque nous pouvons atteindre B de chaque côté de l'obstacle gauche en traversant o depuis l'est , nous devons traiter cet obstacle comme s'il pouvait être franchi par le nord lors de la résolution du parcours; il n'en va pas de même pour le bon obstacle, cependant, qui ne peut pas être traversé dans cette direction.

Nous convertissons ces informations supplémentaires en spécifiant, avec la course d'obstacles, le nombre de caractères le long de la première ligne, en partant de la gauche, sur lequel le chemin peut commencer. Dans le diagramme ci-dessus, cela est décrit comme la ligne continue à côté de chaque cours. Bien que, techniquement, nous devons également spécifier le nombre correspondant de caractères le long de la première colonne à partir de laquelle le chemin peut commencer, comme dans le cas du sous-cours A , en pratique, nous avons toujours sélectionné l'obstacle le plus élevé, de sorte que ces informations ne sont pas requises .

La sélection réelle de o est la suivante: nous prétendons que chaque ligne, autre que la dernière, est suivie d'un obstacle (c.-à-d., A une #annexe), et sélectionnons le premier obstacle dans le parcours résultant, dans l'ordre de lecture. Pour les lignes (autres que la dernière) qui n'avaient pas d'obstacle à l'origine, cela signifie effectivement que nous les ignorons (tout en notant que le chemin ci-dessous peut commencer à n'importe quel caractère le long de la ligne supérieure). Finalement, nous nous retrouvons avec un parcours qui a une seule rangée sans obstacles, pour lequel il n'y a qu'un seul chemin possible.


c'est à peu près la solution que j'envisageais. Je savais que quelqu'un le publierait avant d'en avoir la chance.
quintopie

6

CJam, 85 84 82 81 80 79 octets

qN/:Q,(Qz,(:R_T]2/e~e!{'#Qs@{\(\@>}%s-},{_}{(a\L{@+_@\-_{2$\f.=0fe=2&},}h;}w;],

Essayez-le en ligne. Ou exécutez l'ensemble de la suite de tests.

L'efficacité de cette solution est probablement assez horrible mais elle résout chaque cas de test en quelques secondes.

Explication

Je vais devoir ajouter une ventilation complète du code plus tard, mais l'idée algorithmique est la suivante:

  • Laissez la largeur et la hauteur de la grille soient Wet H, respectivement.
  • Nous générons tous les chemins possibles comme les permutations distinctes des W-1copies de 0et des H-1copies de W-1(où 0représente une étape horizontale et W-1une étape verticale). Nous parcourons tous ces chemins en prenant à plusieurs reprises le premier élément de la grille, puis en sautant les stepcellules dans l'ordre de lecture (où stepest 0ou W-1). Nous rejetons tous les chemins qui contiennent a #.
  • Ensuite, nous supprimons à plusieurs reprises un groupe de chemins similaires (qui seront tous les chemins similaires au premier des chemins restants). La vérification de chemins similaires devient un peu plus facile en assouplissant légèrement la condition pour eux: au lieu de vérifier si l'un xa bougé, nous vérifions si les chemins diffèrent exactement à deux endroits. Si tel est le cas, ces deux endroits auront un déplacement vertical et horizontal inversé. Cela provoque le décalage du segment entier entre ces mouvements en diagonale d'une cellule. Mais si ces deux chemins sont valides, le déplacement d'une partie du chemin d'une cellule en diagonale ne peut pas traverser un obstacle, ils sont donc similaires. Nous devons encore trouver la fermeture transitive, alors nous continuons à le faire jusqu'à ce que nous ne trouvions plus de chemins similaires avant de passer au groupe suivant.
  • Enfin, nous comptons les groupes que nous avons trouvés, que nous avons laissés au bas de la pile.
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.