introduction
Il y a un collecteur d'impôts qui a du mal à gérer les impôts de son royaume: les documents historiques ont brûlé dans un grand incendie.
Il veut savoir combien de passés possibles il pourrait y avoir en termes de provenance de l'argent actuel. Heureusement, son royaume est très simple.
Le royaume peut être modélisé par une matrice booléenne 2D, où l
représente quelqu'un qui a hérité de l'argent et O
représente quelqu'un qui ne l'a pas. Par exemple:
l O l l
O O O l
l O l O
O O O l
(Ce sera toujours un rectangle)
Dans la génération suivante, le royaume est plus petit (les loups sont forts!).
La prochaine génération ressemblerait à ceci, superposée à la génération précédente ( x
est un espace réservé pour un descendant de la génération suivante)
l O l l
x x x
O O O l
x x x
l O l O
x x x
O O O l
Descendante se penchera sur les ancêtres qui sont directement autour d' eux (donc en haut à gauche x
verra { l
, O
, O
, O
}, appelé un quartier rectangulaire Unaligned )
Si un seul ancêtre a hérité de l'argent, le descendant en héritera. Si plus d'un ancêtre a hérité de l'argent, ils se disputeront et le descendant finira par ne pas hériter de l'argent. Si personne n'a hérité d'argent, le descendant n'héritera pas d'argent.
(Plus d'un descendant peut hériter d'un ancêtre)
Ainsi, la prochaine génération ressemblerait à:
l l O
l l O
l l O
Défi
Contribution
L'état actuel de la génération, sous la forme d'un tableau de tableaux de deux valeurs distinctes, où les tableaux internes sont tous de la même longueur.
Par exemple, pour l'exemple ci-dessus, cela pourrait être:
[
[True, True, False],
[True, True, False],
[True, True, False]
]
Production
Un entier représentant le nombre de générations précédentes uniques où la génération suivante est l'entrée.
Vous pouvez supposer que la réponse sera toujours inférieure à 2 ^ 30 - 1. (ou 1073741823).
La génération précédente s'appellerait une "préimage" et ce défi serait de compter les préimages .
Notation
C'est un défi de code le plus rapide , donc chaque soumission sera testée sur mon ordinateur, et la soumission qui prend le moins de temps sera gagnante.
Exemple d'entrée et de sortie
(Où 1
est un descendant qui a hérité de l'argent, et 0
est un descendant qui n'a pas hérité de l'argent)
Contribution:
[[1, 0, 1],
[0, 1, 0],
[1, 0, 1]]
Production:
4
Contribution:
[[1, 0, 1, 0, 0, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0],
[1, 1, 1, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 0, 1, 1, 1]]
Production:
254
Contribution:
[[1, 1, 0, 1, 0, 1, 0, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 1, 1, 0, 0]]
Production:
11567
Réponses:
C ++ à l'aide de la bibliothèque BuDDy
Cela semblait être une bonne excuse pour jouer avec des diagrammes de décision binaires . Le royaume est converti en une grande formule booléenne où il faut compter le nombre de façons dont il peut être satisfait. Cela peut (parfois) être fait plus efficacement qu'il n'y paraît.
Le royaume doit être donné comme une constante de programme comme un tableau plat et des dimensions explicitement données. (Une belle entrée est laissée en exécution pour le lecteur :-)
Voici le code d'une simplicité embarrassante:
Pour compiler avec Debian 8 (Jessie), installez
libbdd-dev
et faitesg++ -std=c++11 -o hist hist.cpp -lbdd
. (Les options d'optimisation ne font pratiquement aucune différence car le vrai travail est effectué dans la bibliothèque.)De grands exemples peuvent conduire à des messages sur la récupération de place. Ils pourraient être supprimés, mais je préfère les voir.
bdd_satcount
renvoie undouble
, mais cela suffit pour la plage de résultats attendue. La même technique de comptage est possible avec des (grands) entiers exacts.Le code est optimisé pour
ROWS<COLS
. Si vous avez beaucoup plus de lignes que de colonnes, ce pourrait être une bonne idée de transposer la matrice.la source
Python 2.7
Ce n'est qu'une première tentative naïve. Ce n'est pas particulièrement rapide, mais c'est correct.
La première observation est que chaque cellule dépend exactement de quatre cellules de la génération précédente. Nous pouvons représenter ces quatre cellules sous la forme d'un nombre à 4 bits (0-15). Selon les règles, si exactement une cellule voisine de la génération précédente l'est
1
, alors une cellule donnée de la génération actuelle le sera1
, sinon, elle le sera0
. Ceux-ci correspondent aux pouvoirs de deux, à savoir[1, 2, 4, 8]
. Lorsque les quatre ancêtres sont représentés comme un nombre à 4 bits, tout autre nombre entraînera un0
dans la génération actuelle. Avec ces informations, en voyant une cellule de la génération actuelle, nous pouvons réduire les possibilités du voisinage de la génération précédente à l'une des quatre ou une des douze possibilités respectivement.J'ai choisi de représenter le quartier comme suit:
où 0 est le bit le moins significatif, et ainsi de suite.
La deuxième observation est que pour deux cellules adjacentes de la génération actuelle, les deux quartiers de la génération précédente se chevauchent:
ou:
Dans le cas horizontal, le
2
quartier de gauche chevauche le3
quartier de droite et de même avec le0
côté gauche et le1
côté droit. Dans le cas vertical, le1
voisinage supérieur chevauche le3
voisinage inférieur et, de la même manière0
, le sommet et2
le bas.Ce chevauchement signifie que nous pouvons réduire les possibilités de quartiers encore non choisis en fonction de ce que nous avons déjà choisi. Le code fonctionne de gauche à droite, de haut en bas, dans une recherche récursive en profondeur pour les pré-images possibles. Le diagramme suivant indique les quartiers précédents que nous devons prendre en compte lorsque nous examinons les quartiers possibles d'une cellule actuelle:
Voici le code:
Pour l'exécuter:
la source
O(<something>^n)
je pense.)