La tâche
- Vous obtenez une chaîne mutable qui correspond
[a-z]+( [a-z]+)*
. - Vous devez le muter dans la chaîne qui contient les mêmes mots, mais dans l'ordre inverse, pour que "bonjour tout le monde" devienne "tout le monde bonjour".
- Vous n'êtes pas autorisé à utiliser plus d'une quantité constante de mémoire supplémentaire (donc pas de copier la chaîne entière ou un mot entier dans un tampon que vous venez d'allouer).
- Il n'y a pas de contraintes de temps. Être désespérément inefficace ne nuira pas à votre score.
- Si la langue de votre choix ne permet pas la mutation des chaînes, les tableaux de caractères sont un substitut acceptable.
Ton score
- Votre score est compté uniquement sur le nombre d'assignations que vous faites aux éléments de chaîne (les petits scores sont les meilleurs). Si vous utilisez une fonction de bibliothèque qui écrit dans la chaîne, ses écritures comptent également.
- Supposons que le nombre d'affectations dont vous avez besoin pour l'entrée s soit n (s) . Votre score est alors le maximum (pédantiquement, supremum) sur toutes les entrées s (correspondant à l'expression régulière spécifiée ci-dessus) de n (s) / longueur (s) . Si vous ne pouvez pas calculer cela avec précision, vous pouvez utiliser la borne supérieure la plus basse que vous pouvez prouver.
- Vous pouvez rompre une égalité si vous pouvez prouver que votre algorithme utilise asymptotiquement moins d'affectations (cela peut arriver même si vous avez le même score, voir ci-dessous). Si vous ne pouvez pas le faire, vous pouvez rompre une égalité en montrant que vous utilisez moins de mémoire supplémentaire. Cependant, la première condition de départage est toujours prioritaire.
- Pour certaines entrées, chaque personnage doit changer, il n'est donc pas possible de marquer moins de 1.
- Je peux penser à un algorithme simple avec un score de 2 (mais je n'y entre pas).
Notes sur suprema et liens
- Un supremum d'un ensemble de nombres est le plus petit nombre qui n'est pas inférieur à aucun d'entre eux. Cela ressemble beaucoup au maximum d'un ensemble, sauf que certains ensembles infinis comme {2/3, 3/4, 4/5, 5/6, ...} n'ont pas d'élément maximum unique, mais auront toujours un supremum, dans ce cas 1.
- Si vous parvenez à «enregistrer» seulement un nombre constant d'affectations sur mon algorithme de score 2 (disons), votre score sera toujours de 2, car vous obtiendrez arbitrairement près de 2 plus votre entrée sera importante. Cependant, vous gagnez au tie-break s'il s'agit de cela.
code-challenge
Ben Millwood
la source
la source
little-omega(1)
espace en le mettant sur la pile.O(1)
un espace supplémentaire. Vous avez besoin d'O(log n)
espace pour stocker une position d'index, car un entier de k bits ne peut y être stocké que pour des chaînes d'une longueur allant jusqu'à2^k
. Limiter la longueur des chaînes rend le défi plutôt inutile, car chaque algorithme nécessiterait de l'O(1)
espace de cette façon.Réponses:
Python, Score:
21,51,25Ceci est la directe combinaison entre la réponse de primo et ma réponse. Alors merci aussi à lui!
La preuve est toujours en cours, mais voici le code avec lequel jouer! Si vous pouvez trouver un contre-exemple de score supérieur à 1,25 (ou s'il y a un bug), faites le moi savoir!
Actuellement, le pire des cas est:
où il y a exactement n de chacune des lettres "a", "b", "c" et "" (espace), et exactement deux "d" s. La longueur de la chaîne est 4n + 2 et le nombre d'affectations est 5n + 2 , ce qui donne un score de 5/4 = 1,25 .
L'algorithme fonctionne en deux étapes:
k
tel questring[k]
etstring[n-1-k]
sont des limites de motsstring[:k]+string[n-1-k:]
(c'est-à-dire, concaténation des premierk
et dernierk
caractères) avec une petite modification.où
n
est la longueur de la chaîne.L'amélioration apportée par cet algorithme provient de la "petite modification" à l'étape 2. C'est essentiellement la connaissance que dans la chaîne concaténée, les caractères en position
k
etk+1
sont des limites de mot (ce qui signifie qu'ils sont des espaces ou le premier / dernier caractère d'un mot), et nous pouvons donc remplacer directement les caractères en positionk
etk+1
par le caractère correspondant dans la chaîne finale, en économisant quelques affectations. Cela supprime le pire des cas de l'algorithme d'inversion de mot hôteIl y a des cas où nous ne pouvons pas réellement trouver un tel
k
, dans ce cas, nous exécutons simplement "n'importe quel algorithme d'inversion de mot" sur la chaîne entière.Le code est long pour gérer ces quatre cas lors de l'exécution de l'algorithme d'inversion de mot sur la chaîne "concaténée":
k
est introuvable (f_long = -2
)string[k] != ' ' and string[n-1-k] != ' '
(f_long = 0
)string[k] != ' ' and string[n-1-k] == ' '
(f_long = 1
)string[k] == ' ' and string[n-1-k] != ' '
(f_long = -1
)Je suis sûr que le code peut être raccourci. Actuellement, c'est long parce que je n'avais pas une image claire de tout l'algorithme au début. Je suis sûr que l'on peut le concevoir pour être représenté dans un code plus court =)
Sample run (le premier est le mien, le second est celui de primo):
Vous pouvez voir que le score est presque le même, à l'exception du pire cas de l'algorithme d'inversion de mot hôte dans le troisième exemple, pour lequel mon approche donne un score inférieur à 1,25
Python, score: 1,5
Le nombre exact d'affectations peut être approximé par la formule:
le pire des cas étant:
avec 55 affectations sur une chaîne de longueur 37.
L'idée est similaire à la précédente, c'est juste que dans cette version j'ai essayé de trouver le préfixe et le suffixe aux limites des mots avec une différence de longueur au plus 1. Ensuite, je lance mon algorithme précédent sur ce préfixe et ce suffixe (imaginez-les comme étant concaténés) . Continuez ensuite sur la partie non traitée.
Par exemple, pour le pire des cas précédent:
nous allons d'abord faire l'inversion des mots sur "ab" et "c" (4 affectations) pour être:
Nous savons qu'à la frontière, c'était de l'espace (il y a beaucoup de cas à gérer, mais vous pouvez le faire), nous n'avons donc pas besoin de coder l'espace à la frontière, c'est la principale amélioration par rapport à l'algorithme précédent .
Enfin, nous courons sur les quatre caractères du milieu pour obtenir:
au total 8 affectations, l'optimum pour ce cas, puisque les 8 caractères ont changé.
Cela élimine le pire des cas dans l'algorithme précédent puisque le pire des cas dans l'algorithme précédent est éliminé.
Voir un exemple d'exécution (et comparaison avec la réponse de @ primo - c'est la deuxième ligne):
la réponse de primo est généralement meilleure, bien que dans certains cas, je puisse avoir un avantage de 1 point =)
De plus, son code est beaucoup plus court que le mien, haha.
Python, Score: asymptotiquement 2, en cas normal beaucoup moins
l'ancien code a été supprimé en raison d'une contrainte d'espace
L'idée est de parcourir chaque index, et pour chaque index
i
, nous prenons le caractère, calculons la nouvelle positionj
, mémorisons le caractère à la positionj
, assignons le caractère ài
àj
et répétons avec le caractère à l'indexj
. Puisque nous avons besoin des informations d'espace pour calculer la nouvelle position, j'encode l'ancien espace comme la version majuscule de la nouvelle lettre et le nouvel espace comme '@'.la source
length(string)/3
en forçant chaque mot dans le pire des cas à être au moins de longueur 2 d'une manière ou d'une autre), alors le score sera inférieur à 2 (dans l'exemple ci-dessus ce sera 1,67)if any(process_loop(...) for j in range(...))
les affectations de ces boucles de processus ne devraient-elles pas être comptées?dry_run
paramètre est défini sur non nul (la valeur ài
). À l'intérieur duprocess_loop
, s'ildry_run
est différent de zéro, il ne fera aucune affectation.Perl, score 1,3̅
Pour chaque caractère non espace, une affectation est effectuée et pour chaque caractère espace deux affectations.
Étant donné que les caractères d'espace ne peuvent pas représenter plus de la moitié du nombre total de caractères, le score le plus défavorable est de 1,5 .L'algorithme n'a pas changé, mais je peux prouver une limite supérieure inférieure. Faisons deux observations:
On peut alors voir que le «pire cas» théorique avec 1/2 espace asymptotique n'est pas du tout le pire:
ab c d e f g h i ...
En fait, c'est un assez bon cas.
Afin d'empêcher l'observation un et deux ci-dessus, chaque mot d'un caractère devrait être repositionné au milieu d'un mot de trois caractères ou plus. Cela suggérerait un pire cas contenant 1/3 espaces asymptotiquement:
a bcd a bcd a ... bc
Ou de manière équivalente, seuls les mots à deux caractères:
a bc de fg hi jk ...
Parce que le pire des cas contient asymptotiquement 1/3 d'espaces, le score du pire cas devient 1,3̅ .
Modifier: Ajout d'un compteur de swap et du ratio.
L'entrée provient de stdin. Exemple d'utilisation:
Méthode
Pour commencer, le premier caractère de la chaîne est déplacé vers sa destination finale. Le personnage qui vient d'être remplacé est ensuite déplacé vers sa destination, etc. Cela continue jusqu'à ce que l'une des deux conditions soit remplie:
Lorsque cela se produit, le personnage n'est pas échangé avec l'espace, mais plutôt dans la position miroir de l'espace. L'algorithme continue à partir de cette position.
Lorsque la cible revient à la position de départ initiale du cycle en cours, le prochain caractère non permuté (ou plutôt, n'importe quel caractère non permuté ferait) doit être trouvé. Pour ce faire, sous des contraintes de mémoire constantes, tous les échanges qui ont été effectués jusqu'à ce point sont retracés.
Après cette phase, chaque personnage non-espace a été déplacé au plus une fois. Pour terminer, tous les caractères d'espace sont échangés avec les caractères à leur position miroir, ce qui nécessite deux opérations d'affectation par espace.
la source
Ruby, score 2
En entrée un algorithme très basique. Il inverse d'abord la chaîne entière puis inverse à nouveau chaque mot de la chaîne. Dans le pire des cas (un mot, nombre pair de caractères) le score devient 2.
Usage:
la source
C ++: Score 2
la source
Rebol
Je ne suis pas clair sur le score pour cela. Il n'y a pas d'affectation de chaîne directe dans ce code. Tout est géré par l'un
reverse/part
qui fait la réversibilité en place à l'intérieur et initialement sur l'ensemble de la chaîne.Quelques détails sur le code:
Boucle à travers la chaîne (
series
) jusqu'à ce qu'elle atteigne letail?
Première fois en boucle, inversez complètement la chaîne -
reverse/part series tail series
(ce qui est le même quereverse series
)Inversez ensuite chaque mot trouvé sur les itérations suivantes -
reverse/part series find series space
Une fois le mot épuisé trouvé, retournez-le
tail series
afin qu'il inverse le dernier mot de la chaîne -reverse/part series tail series
Rebol permet de parcourir une chaîne via un pointeur interne . Vous pouvez le voir à
series: next f
(déplacer le pointeur vers l'espace après le début du mot suivant) etseries: head series
(réinitialise le pointeur à la tête).Voir la série pour plus d'informations.
Exemple d'utilisation dans la console Rebol:
la source
C: Score 2
Cela retourne une fois la chaîne entière puis inverse chaque mot.
la source
Python: score 2
Presque identique à l'algorithme d'Howard, mais effectue les étapes d'inversion dans le sens inverse (retourne d'abord les mots puis retourne la chaîne entière). Occasion mémoire supplémentaire est de 3 octets des variables de taille:
i
,j
, ett
. Techniquement,find
etlen
utilisent certaines variables internes, mais elles pourraient tout aussi bien être réutiliséesi
ouj
sans perte de fonction.édition rapide: économiser sur les affectations de chaînes en n'échangeant que lorsque les caractères diffèrent, donc je peux récupérer quelques points supplémentaires de la note # 2.
la source
Lot
J'avoue ne pas bien comprendre le score (je pense que c'est deux) .. mais je dirai - ça fait le truc .
L'entrée est considérée comme la première valeur d'entrée standard et doit donc être entourée de guillemets -
appelez:
script.bat "hello there everyone"
out:
everyone there hello
.Peut-être que quelqu'un d'autre peut me marquer (en supposant que je ne me suis pas disqualifié d'une autre manière).
la source
Javascript
Usage:
J'ai l'impression étrange d'avoir raté quelque chose ...
la source