introduction
Supposons que vous et votre ami jouiez à un jeu. Votre ami pense à une séquence particulière de n
bits et votre tâche consiste à en déduire la séquence en lui posant des questions. Cependant, le seul type de question que vous êtes autorisé à poser est "Quelle est la longueur de la sous-séquence commune la plus longue de votre séquence et S
", où se S
trouve toute séquence de bits. Moins vous avez besoin de questions, mieux c'est.
La tâche
Votre tâche consiste à écrire un programme ou une fonction qui prend en entrée un entier positif n
et une séquence binaire R
de longueur n
. La séquence peut être un tableau d'entiers, une chaîne ou un autre type raisonnable de votre choix. Votre programme doit sortir la séquence R
.
Votre programme n'est pas autorisé à accéder R
directement à la séquence . La seule chose qu'il est autorisé à faire R
est de le donner comme entrée à la fonction len_lcs
avec une autre séquence binaire S
. La fonction len_lcs(R, S)
renvoie la longueur de la sous-séquence commune la plus longue de R
et S
. Cela signifie la séquence de bits la plus longue qui se présente comme une sous-séquence (pas nécessairement contiguë) dans les deux R
et S
. Les entrées len_lcs
peuvent être de longueurs différentes. Le programme doit appeler cette fonction R
et d'autres séquences un certain nombre de fois, puis reconstruire la séquence en R
fonction de ces informations.
Exemple
Considérez les entrées n = 4
et R = "1010"
. Tout d'abord, nous pourrions évaluer len_lcs(R, "110")
, ce qui donne 3
, puisque "110"
c'est la sous-séquence commune la plus longue de "1010"
et "110"
. Ensuite, nous savons que cela R
est obtenu "110"
en insérant un bit à une certaine position. Ensuite, nous pourrions essayer len_lcs(R, "0110")
, qui retourne 3
puisque les sous-séquences communes les plus longues sont "110"
et "010"
, ce "0110"
n'est donc pas correct. Ensuite, nous essayons len_lcs(R, "1010")
, qui revient 4
. Nous le savons maintenant R == "1010"
, nous pouvons donc renvoyer cette séquence comme sortie correcte. Cela a nécessité 3 appels vers len_lcs
.
Règles et notation
Dans ce référentiel , vous trouverez un fichier appelé subsequence_data.txt
contenant 100 séquences binaires aléatoires de longueurs comprises entre 75 et 124. Elles ont été générées en prenant trois flottants aléatoires entre 0 et 1, en prenant leur moyenne en tant que a
, puis en a
inversant un temps de pièce biaisé n
. Votre score est le nombre moyen d'appels verslen_lcs
ces séquences, un score plus bas étant meilleur. Votre soumission doit enregistrer le nombre d'appels. Il n'y a pas de limite de temps, sauf que vous devez exécuter votre programme sur le fichier avant de le soumettre.
Votre soumission sera déterministe. Les PRNG sont autorisés, mais ils doivent utiliser la date du jour 200116
(ou l'équivalent le plus proche) comme valeur de départ aléatoire. Vous n'êtes pas autorisé à optimiser votre soumission par rapport à ces cas de test particuliers. Si je soupçonne que cela se produit, je vais générer un nouveau lot.
Ce n'est pas du golf de code, vous êtes donc encouragé à écrire du code lisible. Rosetta Code a une page sur la sous-séquence commune la plus longue ; vous pouvez l'utiliser pour l'implémenter len_lcs
dans la langue de votre choix.
lcs
place delen_lcs
.lcs(R, "01"*2*n)
revientR
. ;) Mais cela pourrait fonctionner si appelerlcs(R, S)
augmentait le score aulen(S)
lieu de 1, ou quelque chose comme ça ...Réponses:
Java,
99,0498,4697,66 lcs () appelsComment ça fonctionne
Exaple: Notre ligne à reconstruire est
00101
. Nous découvrons d'abord combien de zéros il y a, en comparant (ici en comparant = calcul des LC avec la chaîne d'origine) par une chaîne de zéros uniquement00000
. Ensuite, nous passons par chaque position, retournons le0
à a1
et vérifions si nous avons maintenant une sous-chaîne commune plus longue. Si oui, acceptez et passez à la position suivante, sinon, retournez le courant1
à a0
et passez à la position suivante:Optimisations
Ceci est juste une implémentation "naïve", il serait peut-être possible de trouver un alogrithme plus sophistiqué vérifiant plusieurs positions à la fois. Mais je ne sais pas s'il vraiment est un meilleur (par exemple basé sur le calcul des bits de parité similaires au code Hamming), comme vous pouvez toujours évaluer juste la longueur de la sous - chaîne commune.
Pour une ligne de chiffres donnée, cet algorithme a besoin de
#ofDigitsUntilTheLastOccurenceOf1 + 1
vérifications précises. (Soustrayez-en un si les derniers chiffres sont un1
.)EDIT: Une petite optimisation: si nous venons de vérifier le deuxième dernier chiffre et que nous devons encore insérer un
1
, nous savons avec certitude qu'il doit être dans la toute dernière position et peut omettre la vérification correspondante.EDIT2: Je viens de remarquer que vous pouvez appliquer l'idée ci-dessus aux dernières
k
.Il pourrait bien sûr être possible d'obtenir un score légèrement inférieur avec cette optimisation, en réorganisant d'abord toutes les lignes, car il se pourrait que vous obteniez plus de lignes avec celles à la toute fin, mais ce serait évidemment une optimisation pour le courant cas de test qui n'est plus drôle.
Durée
La limite supérieure est
O(#NumberOfBits)
.Code complet
Voici le code complet:
la source
1
, ce qui équivaut à ce qu'il ne reste que des zéros.