Converti 1 in qualsiasi numero intero positivo usando solo le operazioni * 3 e / 2


11

Qualsiasi numero intero positivo può essere ottenuto iniziando con 1 e applicando una sequenza di operazioni, ognuna delle quali è "moltiplica per 3" o "divide per 2, scartando ogni resto" .

Esempi (scrivendo f per * 3 eg per / 2):

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

Scrivi un programma con il seguente comportamento:

Input : qualsiasi numero intero positivo, tramite stdin o hard-coded. (Se codificato, il numero di input verrà escluso dalla lunghezza del programma.)
Output : una stringa di f e g tale che <input> = 1 <string>(come negli esempi). È accettabile anche una tale stringa in ordine inverso. NB: L'output contiene solo f e g oppure è vuoto.

Il vincitore è la voce con il minor numero di byte di programma più un output quando 41 è l'input.


1
Come fai a sapere che è vero?
Marin

@marinus questo è ritenuto vero (ma non ancora provato). in cerca di qualche prova.
Fabinout,

@marinus, puoi dimostrare che è possibile per discesa (o equivalentemente per forte induzione). Dividi caso x mod 3: se x=3ycostruisci y e poi applica f; se x=3y+1costruire 2y+1e applicare fquindi g; se x=3y+2poi diventa complicato ma essenzialmente è ricorsivo.
Peter Taylor,

In una nota a parte, l'output deve essere nell'ordine dell'applicazione o l'ordine di composizione dovrebbe essere accettabile?
Peter Taylor,

@PeterTaylor In entrambi i casi è OK.
res

Risposte:


3

GolfScript, punteggio 64 (43-2 + 23)

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

(41 è hardcoded, quindi -2 caratteri per il punteggio). L'output è

fffgffggffggffgggffgggg

che è di 23 caratteri (senza newline). Per costruzione il codice garantisce che restituisce sempre (una delle) rappresentazioni più brevi.


Citando l'utente Darren Stone in una modifica suggerita in questo post: "Non riesco a lasciare un commento qui, quindi lascerò una modifica. Questo output non include i primi due caratteri" 1 "né quelli che si riflettono nel punteggio. Dovrebbe essere un soluzione semplice e ancora una soluzione incredibilmente breve. Saluti! " (Ho rifiutato, ma ho pensato che avrei dovuto portare il messaggio)
Maniglia della porta

@Doorknob La sfida afferma che "1 "non dovrebbe essere incluso nell'output.
Howard,

3

Ci stiamo sporcando, amici!

GIAVA 210 207 199 caratteri

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 giocato a 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);
    }
}

output: a seconda della fede dei vecchi dei, il più corto che ho avuto era 30. Nota che l'output deve essere letto da destra.

234

1 ggfgfgfgfggfggfgffgfggggfgffgfggfgfggggfgffgfggfgfggfgfggfgfgggggfffgfggfgfggfgfgggffgggggfffgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggfgfggggfgffgfggfgfggfgfggfgfggfgfggfgfggggggggggggfgfgfggggfgfgfggfffgfgfggffgfgfggfgfggggffgfgfffff

108

1 gggffgfgfggggggfggggfgffggggfgfgfgfgfgffgggfgggggfggfffggfgfffffgggffggfgfgggffggfgfgggffggggggfgfgffgfgfff

modifica 45

1 ggfgfgfgfgggfggfffgfggfgfgggggggffgffgfgfff

punti : 318 199 + 30 = 229

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

Nota Bene se si utilizza Java 6 e non Java 7 mentre si gioca a golf, è possibile utilizzare

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

Struttura di 39 caratteri invece di una struttura standard lunga 53 caratteri.


(2*i+1)%3==0è equivalente ai%3==1
Howard

Sì. grazie
Fabinout,

if(X){A}else{if(Y){B}else{C}}è più lungo di if(X){A}else if(Y){B}else{C}. Inoltre puoi sostituire le tue ==condizioni con <condizioni più brevi .
Peter Taylor,

@PeterTaylor vero, la mia soluzione è ancora brutta. Non so se la parte casuale accorcia il codice, ma sicuramente rende l'output più scadente.
Fabinout,

Le tue stringhe f / g iniziano con 'g' (che dovrebbe rappresentare '/ 2'), quindi convertiranno 1 in 0 anziché in 41. Cambiando le f in g e viceversa, inoltre, non sembra dare 41.
ris

3

Python, punteggio 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 caratteri di codice (newline come 1 ciascuno) - 2 per numeri di input codificati + 36 caratteri di output

Produzione:

ffffffffffffffffgggggggggggggggggggg

1
Se lo fai m=f=0puoi creare il circuito esterno while(n!=x)*(m!=x)e rimuovere le interruzioni. Lo porta a 95 caratteri di codice.
Daniel Lubarov,

@Daniel: Lei, signore, è un gentiluomo e uno studioso. Grazie! La tua richiesta è ancora in sicurezza 10 caratteri davanti a me. :)
Darren Stone,

1
Puoi salvare un po 'di più se lo sostituisci ncon 3**f.
Howard,

1
Per input = 1, il programma genera un errore ("nome 'g' non è definito", a causa della mancata immissione del ciclo while esterno).
res

1
Potresti ritagliare un altro personaggio scrivendo print'f'*f+'g'*g, il che darebbe un punteggio di 90-2 + ​​36 = 124.
Ris

3

Python, punteggio 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'

@Darren, non ero sicuro di come interpretare la descrizione dell'output, ma probabilmente hai ragione. Ho aggiunto "1". Grazie!
Daniel Lubarov,

1
È possibile eliminare "1" (di nuovo!) L'interpretazione originale della descrizione dell'output era corretta. Goditi di nuovo il comando di Python! :-)
Darren Stone,

1
Se hai combinato la tua seconda, terza e quarta riga in l,n,f=len(t),1,0, e hai rimosso la '1',frase di stampa, il tuo punteggio sarebbe 87-2 + 36 = 121.
res

Grazie ragazzi - ho lasciato cadere 1,. l,n,f=len(t),1,0dà lo stesso numero di caratteri, giusto? (Per ogni variabile, una =e una nuova riga vengono sostituite con due ,s.)
Daniel Lubarov

Se ogni newline ha un carattere (es. LF in stile UNIX), le versioni a una e tre righe hanno la stessa lunghezza. Se ogni newline ha due caratteri (ad es. CR + LF in stile MS Windows), la versione a una riga è più corta di due caratteri rispetto alla versione a tre righe. Il punteggio di 121 assume le nuove linee di un carattere.
res

1

Perl, punteggio 89 (63-2 + 28)

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

Congettura: se l'approccio ingenuo descritto nella mia soluzione originale qui sotto raggiunge mai un ciclo, quel ciclo sarà [21, 7, 15, 5, 10, 21, ...] . Dato che non ci sono contro-esempi per 1 ≤ n ≤ 10 6 , questo sembra essere vero. Per dimostrarlo, basterebbe dimostrare che questo è l'unico ciclo che può esistere, cosa che potrei o meno fare in un momento successivo.

La soluzione di cui sopra evita immediatamente il ciclo, invece di indovinare (erroneamente) ed evitarlo la seconda volta.

Uscita (28 byte):

ggfgfgfgfggfggfgfgfggfgfgfff

Perl, punteggio 100 (69-2 + 33)

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

Utilizzando un approccio di indovinare e controllare. La stringa viene costruita utilizzando operazioni inverse (convertendo il valore in 1 , anziché viceversa) e la stringa viene rispecchiata di conseguenza, il che è consentito dalla specifica del problema.

Ogni volta che si incontra un non multiplo di tre, verrà moltiplicato per due, aggiungendo uno se il risultato sarebbe un multiplo di tre. Quando viene rilevato un multiplo di tre, verrà diviso per tre ... a meno che questo valore non sia stato precedentemente rilevato, indicando un ciclo, quindi indovinare e controllare.

Uscita (33 byte):

ggfgfgfgfggfggfgffgfgggfggfgfgfff

1

J, punteggio 103 (82-2 + 23)

* Nota: ho chiamato i miei verbi fe g, da non confondere con le stringhe di output fe g.

Hard-coded:

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

Funzioni generali:

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

Ha eliminato il funzionamento su blocchi di numeri binari, che è stato il cambiamento più importante per quanto riguarda la compattazione g. Rinominato variabili e rimosso alcuni spazi bianchi per il diavolo di esso, ma tutto è ancora funzionalmente uguale. (Usage: g 41)

J, punteggio 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
)

Produzione: ffffffffggggggggfgffggg

fconverte un elenco di valori booleani in numero, usando 0s come *3e 1s come /2(e floor). #:i.2^icrea un array di rango 2 contenente tutti gli array booleani di rango 1 di lunghezza i.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.