Convertir 1 en n'importe quel entier positif en utilisant uniquement les opérations * 3 et / 2

11

Tout entier positif peut être obtenu en commençant par 1 et en appliquant une séquence d'opérations, chacune étant soit «multipliée par 3», soit «divisée par 2, en éliminant tout reste» .

Exemples (écrire f pour * 3 et g pour / 2):

4 = 1 *3 *3 /2 = 1 ffg
6 = 1 ffggf = 1 fffgg
21 = 1 fffgfgfgggf

Écrivez un programme avec le comportement suivant:

Entrée : tout entier positif, via stdin ou codé en dur. (S'il est codé en dur, le numéro d'entrée sera exclu de la longueur du programme.)
Sortie : une chaîne de f et de g telle que <input> = 1 <string>(comme dans les exemples). Une telle chaîne dans l'ordre inverse est également acceptable. NB: La sortie ne contient que des f et g, ou est vide.

Le gagnant est l'entrée avec le moins d'octets de programme-plus-sortie lorsque 41 est l'entrée.

res
la source
1
Comment savez-vous que c'est vrai?
marinus du
@marinus, cela semble vrai (mais pas encore prouvé). à la recherche d'une preuve.
Fabinout
@marinus, vous pouvez prouver que c'est possible par descente (ou de manière équivalente par forte induction). Case-split on x mod 3: si x=3yconstruire y puis appliquer f; si x=3y+1construire 2y+1et appliquer falors g; si x=3y+2alors cela devient compliqué mais essentiellement récursif.
Peter Taylor
Sur une note distincte, la sortie doit-elle être dans l'ordre d'application ou l'ordre de composition est-il également acceptable?
Peter Taylor
@PeterTaylor Dans les deux cas, c'est OK.
res

Réponses:

3

GolfScript, score 64 (43-2 + 23)

0{)1.$2base:s{{3*}{2/}if}/41=!}do;s{103^}%+

(41 est codé en dur, donc -2 caractères pour la partition). La sortie est

fffgffggffggffgggffgggg

qui est de 23 caractères (sans nouvelle ligne). Par construction, le code garantit qu'il renvoie toujours (l'une des) représentations les plus courtes.

Howard
la source
Citant l'utilisateur Darren Stone dans une modification suggérée sur ce post: "Je ne peux pas laisser de commentaire ici, donc je vais laisser une modification. Cette sortie n'inclut pas les deux premiers caractères" 1 "ni ceux qui sont reflétés dans la partition. Devrait être un solution facile et toujours une solution incroyablement courte. Cheers! " (J'ai rejeté, mais j'ai pensé que je devais porter le message)
Poignée de porte
@Doorknob Le défi indique que le "1 "ne doit pas être inclus dans la sortie.
Howard
3

Nous devenons sales, amis!

JAVA 210 207 199 caractères

public class C{public static void main(String[] a){int i=41;String s="";while(i>1){if(i%3<1){s+="f";i/=3;}else if(i%3<2){s+="g";i+=i+1;}else{s+="g";i+=i+(Math.random()+0.5);}}System.out.println(s);}}

non-golfé:

public class C {

    public static void main(String[] a) {

        int i = 41;
        String s = "";
        while (i > 1) {
            if (i % 3 == 0) {
                s += "f";
                i /= 3;
            } else {
                if (i % 3 == 1) {
                    s += "g";
                    i += i + 1;
                } else {
                    s += "g";
                    i += i + (Math.random() + 0.5);
                }
            }
        }
        System.out.println(s);
    }
}

sortie: selon la foi des anciens dieux, la plus courte que j'ai eue était de 30. Notez que la sortie doit être lue à droite.

234

1 ggfgfgfgfggfggfgffgfggggfgffgfggfgfggggfgffgfggfgfggfgfggfgfgggggfffgfggfgfggfgfgggffgggggfffgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggfgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggggggggggggfgfgfggggfgfgfggfffgfgfggffgfgfggfgfggggffgfgfffff

108

1 gggffgfgfggggggfggggfgffggggfgfgfgfgfgffgggfgggggfggfffggfgfffffgggffggfgfgggffggfgfgggffggggggfgfgffgfgfff

modifier 45

1 ggfgfgfgfgggfggfffgfggfgfgggggggffgffgfgfff

points : 318 199 + 30 = 229

edit1 (2 * i + 1)% 3 == 0 -> (2 * i)% 3 == 1

Nota Bene si vous utilisez Java 6 et non Java 7 pendant le golf, vous pouvez utiliser

public class NoMain {
    static {
        //some code
        System.exit(1);
    }
}

Structure de 39 caractères au lieu d'une structure standard de 53 caractères.

Fabinout
la source
(2*i+1)%3==0est équivalent ài%3==1
Howard
Oui, ça l'est. merci
Fabinout
if(X){A}else{if(Y){B}else{C}}est plus long que if(X){A}else if(Y){B}else{C}. Vous pouvez également remplacer vos ==conditions par des <conditions plus courtes .
Peter Taylor
@PeterTaylor true, ma solution est toujours laide. Je ne sais pas si la partie aléatoire rend le code plus court, mais cela rend la sortie encore plus folle.
Fabinout
Vos chaînes f / g commencent par 'g' (qui est censé représenter '/ 2'), donc elles convertiront 1 en 0 au lieu de 41. Changer les f en g et vice versa, ne semble pas non plus donner 41.
res
3

Python, score 124 (90-2 + ​​36)

x=41;m=f=g=0
while(3**f!=x)*(m!=x):
 f+=1;m=3**f;g=0
 while m>x:m/=2;g+=1
print'f'*f+'g'*g

90 caractères de code (sauts de ligne à 1 chacun) - 2 pour le chiffre d'entrée codé en dur + 36 caractères de sortie

Production:

ffffffffffffffffgggggggggggggggggggg
Darren Stone
la source
1
Si vous le faites, m=f=0vous pouvez faire la boucle extérieure while(n!=x)*(m!=x)et supprimer les pauses. Le porte à 95 caractères de code.
Daniel Lubarov
@Daniel: Vous, monsieur, vous êtes un gentleman et un savant. Merci! Votre soumission est toujours en sécurité 10 caractères devant moi. :)
Darren Stone
1
Vous pouvez encore économiser un peu si vous remplacez tout npar 3**f.
Howard
1
Pour input = 1, votre programme génère une erreur ("le nom 'g' n'est pas défini", car vous n'avez pas entré la boucle while externe).
res
1
Vous pouvez couper un autre personnage en écrivant print'f'*f+'g'*g, ce qui donnerait un score de 90-2 + ​​36 = 124.
res
3

Python, score 121 (87-2 + 36)

t=bin(41)
l,n,f=len(t),1,0
while bin(n)[:l]!=t:f+=1;n*=3
print(len(bin(n))-l)*'g'+f*'f'
Daniel Lubarov
la source
@Darren, je ne savais pas comment interpréter la description de sortie, mais vous avez probablement raison. J'ai ajouté le «1». Merci!
Daniel Lubarov
1
Vous pouvez supprimer le «1» (encore!) Votre interprétation originale de la description de sortie était correcte. Profitez à nouveau de la piste Python! :-)
Darren Stone
1
Si vous combiniez vos 2e, 3e et 4e lignes dans l,n,f=len(t),1,0et supprimiez le '1',de la déclaration imprimée, votre score serait de 87-2 + 36 = 121.
rés
Merci les gars - j'ai laissé tomber 1,. l,n,f=len(t),1,0donne le même nombre de caractères, non? (Pour chaque variable, une =et une nouvelle ligne sont remplacées par deux ,s.)
Daniel Lubarov
Si chaque nouvelle ligne est composée d'un caractère (par exemple LF de style UNIX), les versions à une ligne et à trois lignes ont la même longueur. Si chaque nouvelle ligne comporte deux caractères (par exemple, CR + LF de style MS Windows), la version à une ligne est plus courte de deux caractères que la version à trois lignes. Le score de 121 suppose des sauts de ligne à un caractère.
res
1

Perl, score 89 (63-2 + 28)

$_=41;$_=${$g=$_%3||$_==21?g:f}?$_*2+$_%3%2:$_/3while$_>print$g

Conjecture: Si l'approche naïve décrite dans ma solution originale ci-dessous atteint un cycle, ce cycle sera [21, 7, 15, 5, 10, 21, ...] . Comme il n'y a pas de contre-exemples pour 1 ≤ n ≤ 10 6 , cela semble vraisemblablement vrai. Pour le prouver, il suffirait de montrer que c'est le seul cycle qui puisse exister, ce que je pourrai faire ou ne pas faire plus tard.

La solution ci-dessus évite le cycle immédiatement, au lieu de deviner (à tort), et de l'éviter la deuxième fois.

Sortie (28 octets):

ggfgfgfgfggfggfgfgfggfgfgfff

Perl, score 100 (69-2 + 33)

$_=41;1while$_>print$s{$_=$$g?$_*2+$_%3%2:$_/3}=$g=$_%3||$s{$_/3}?g:f

Utiliser une approche de deviner et de vérifier. La chaîne est construite à l'aide d'opérations inverses (conversion de la valeur en 1 , au lieu de l'inverse), et la chaîne est reflétée en conséquence, ce qui est autorisé par la spécification du problème.

Chaque fois qu'un non-multiple de trois est rencontré, il sera multiplié par deux, en ajoutant un si le résultat serait alors un multiple de trois. Lorsqu'un multiple de trois est rencontré, il sera divisé par trois ... sauf si cette valeur a déjà été rencontrée, indiquant un cycle, donc devinez et vérifiez.

Sortie (33 octets):

ggfgfgfgfggfggfgffgfgggfggfgfgfff
primo
la source
1

J, score 103 (82-2 + 23)

* Remarque: j'ai nommé mes verbes fet g, à ne pas confondre avec les chaînes de sortie fet g.

Codé en dur:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
'gf'{~#:(>:^:(41&~:@f@#:)^:_)1

Fonctions générales:

f=:3 :'s=.1 for_a.y do.s=.((<.&-:)`(*&3)@.a)s end.'
g=:3 :'''gf''{~#:(>:^:(y&~:@f@#:)^:_)1'

Supprimé le fonctionnement sur des blocs de nombres binaires, ce qui était le changement le plus important en ce qui concerne le compactage g. Changement de nom des variables et suppression d'espaces pour le mieux, mais tout est toujours le même sur le plan fonctionnel. (Utilisation: g 41)

J, score 197 (174 + 23)

f =: 3 : 0
acc =. 1
for_a. y do. acc =. ((*&3)`(<.&-:)@.a) acc end.
)

g =: 3 : 0
f2 =: f"1 f.
l =. 0$0
i =. 1
while. 0=$(l=.(#~(y&=@:f2))#:i.2^i) do. i=.>:i end.
'fg'{~{.l
)

Production: ffffffffggggggggfgffggg

fconvertit une liste de booléens en nombre, en utilisant 0 comme as *3et 1 comme as /2(et floor). #:i.2^icrée un tableau de rang 2 contenant tous les tableaux booléens de rang 1 de longueur i.

rationalis
la source