Determina se un numero intero è divisibile per 3


20

Il tuo obiettivo è determinare se un numero è divisibile per 3 senza usare i condizionali. L'ingresso sarà un numero di 8 bit senza segno da 0 a 255. Creatività incoraggiata!

Hai il permesso di utilizzare SOLO

  • Uguaglianza / disuguaglianza ( ==, !=, >, <, >=, <=)

  • Aritmetica ( +, -, x)

  • Operatori logici ( !non, &&e, || o)

  • Bitwise Operatori ( ~non, &e, |o, ^xor, <<, >>, >>>sinistra aritmetica e logica e si sposta a destra)

  • Costanti (sarebbe meglio se li tenessi piccoli)

  • Assegnazione variabile

Uscita 0se falso, 1se vero.

Si applicano le regole standard di golf atomico. In caso di domande, lasciarle nei commenti. Metodi di esempio qui . Un token è una delle costanti e variabili escluse sopra.


@GregHewgill Il mio errore di battitura, dovrebbe essere un numero di 8 bit.
qwr,

2
Ci è consentito utilizzare solo gli operatori sopra indicati? Altrimenti, modulo renderebbe questo modo troppo semplice.
Jwosty,

Inoltre, che ne dici di cercare una tabella?
Greg Hewgill,

3
Puoi chiarire cosa intendi senza condizionali? È limitato alle istruzioni IF o si applica anche a cose come i loop?
Ruslan,

1
@Ruslan Puoi utilizzare solo quanto sopra.
qwr,

Risposte:


31

C - 2 token

int div3(int x) {
    return x * 0xAAAAAAAB <= x;
}

Sembra funzionare fino a 2 31 -1.

Ringraziamenti zalgo("nhahtdh")per l'idea inversa moltiplicativa.


1
+1. È stato un po 'sconcertato dal modo in cui <=funziona e ha ricordato che 0xAAAAAAAB è considerato come unsigned inttipo, quindi il risultato della moltiplicazione non è firmato.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Gli operatori di disuguaglianza di @DigitalTrauma sono ammessi, non vietati
aditsu,

@aditsu Oops! Ho bisogno di leggere più attentamente a volte! +1 ottima risposta!
Digital Trauma,

@aditsu, mi dispiace, noob, come funziona esattamente?
Kartik_Koro,

2
@Kartik_Koro 0xAAAAAAAB * 3 == 1 a causa di overflow, quindi per qualsiasi int x, x * 0xAAAAAAAB * 3 == x. Anche y * 3 ha valori diversi per y diversi, quindi y = x * 0xAAAAAAAB deve essere l'unico y tale che y * 3 == x. Se x è un multiplo di 3, allora y deve essere x / 3, altrimenti deve funzionare tramite overflow. Un modo semplice per verificare è confrontare y con x. Vedi anche en.wikipedia.org/wiki/Modular_multiplicative_inverse
aditsu

17

Python, 3 token 2

Soluzione di forza bruta, ma funziona.

0x9249249249249249249249249249249249249249249249249249249249249249>>x&1

Grazie a Howard per la riduzione di 1 token.


Wow! La tua soluzione è probabilmente la più breve (3 token), ma voglio incoraggiare anche altre risposte.
qwr,

11
C'è anche una soluzione Token 2: 0x9......>>x&1.
Howard,

6

C - 5 4 (?) Token

int div3_m2(uint32_t n) {
    return n == 3 * (n * 0xAAAAAAABull >> 33);
}

Funziona con qualsiasi numero a 32 bit senza segno .

Questo codice utilizza il modulo 2 32 inverso moltiplicativo di un divisore per convertire l'operazione di divisione in operazione di moltiplicazione.

modificare

La mia soluzione (pubblicata 2 minuti dopo) ha lo stesso spirito della soluzione di Aditsu. Ringraziandolo per l'uso ==che migliora la mia soluzione di 1 token.

Riferimento


1
Questo è incredibile. Conoscevo i numeri magici del famoso trucco inverso dello squareroot, ma non sapevo che potesse essere usato per un divisore arbitrario. Questo è Bull: P
qwr,

Sì, 0xAAAAAAAB = (2 ^ 33 + 1) / 3 e 171 = (2 ^ 9 + 1) / 3. Ho scelto la costante più piccola che fa il trucco. Hmm, in realtà sembra funzionare anche con 86 = (2 ^ 8 + 2) / 3
aditsu,

Ratti, anche 43 = (2 ^ 7 + 1) / 3 funziona, non sono sicuro di come mi sia perso. Modificato ora.
aditsu,

4

C - 15 token (?)

int div3_m1(unsigned int n) {
    n = (n & 0xf) + (n >> 4);
    n = (n & 0x3) + (n >> 2);
    n = (n & 0x3) + (n >> 2);
    return n == 0 || n == 3;
}

Da 4 ≡ 1 (mod 3), abbiamo 4 n ≡ 1 (mod 3). La regola di somma delle cifre non si limita alla somma delle cifre, ma ci consente anche di suddividere arbitrariamente il numero in sequenze di cifre e di sommarle tutte mantenendo la congruenza.

Un esempio in base 10, divisore = 9:

1234 ≡ 12 + 34 ≡ 1 + 2 + 3 + 4 ≡ 123 + 4 ≡ 1 (mod 9)

Tutte le istruzioni nel programma fanno uso di questa proprietà. In realtà può essere semplificato in un ciclo che esegue l'istruzione n = (n & 0x3) + (n >> 2);fino a n < 4quando l'istruzione semplicemente interrompe il numero in base-4 alla cifra meno significativa e aggiunge le 2 parti.


+1: interessante questo funziona per n fino a 512 (in realtà n = 590), ma non sono del tutto sicuro del perché.
Paul R,

@PaulR: non funzionerà per numeri più grandi a causa del trasporto (nota che ho usato l'aggiunta nel calcolo). Nota anche le righe ripetute.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳,

Sì, non sono sicuro del perché funzioni con valori a 9 bit, poiché sembra testare solo 8 bit?
Paul R,

per i numeri 9 bit dopo la prima aggiunta diventa al massimo 5 bit, dopo il primo n = (n & 0x3) + (n >> 2);risultato è ridotto a 3 bit e la ripetizione causato di rimanere solo 2 bit stackoverflow.com/a/3421654/995714
phuclv

1
oh ho fatto un errore. Un numero a 5 bit + un numero a 4 bit può comportare un numero a 6 bit. Ma se n <= 588 aggiungendo i 4 bit superiori e i 2 bit inferiori di quel numero a 6 bit produce una somma di soli 4 bit. Ancora una volta aggiungendo che si ottiene un numero a 2 bit. 589 e 590 danno come risultato 3 bit nell'ultima somma, ma per inciso non sono divisibili per 3, quindi il risultato è corretto
phuclv,

2

Python (2 token?)

1&66166908135609254527754848576393090201868562666080322308261476575950359794249L>>x

O

1&0x9249249249249249249249249249249249249249249249249249249249249249L>>x

O

1&0b1001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001>>x

2
Duplica del commento di Howard
aditsu,

@aditsu ... Le grandi menti pensano allo stesso modo? Giuro che non l'ho visto prima di aver pubblicato questo.
ɐɔıʇǝɥʇuʎs,

2

JavaScript: 3 token

function div3(n) {
    var a = n * 0.3333333333333333;
    return (a | 0) == a;
}

Ciò abusa del fatto che l'utilizzo di operatori bit a bit su un numero lo tronca a un numero intero in JavaScript.


Dovrebbe essere 4 gettoni: =, *, |,==
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

1
Non penso che l'assegnazione delle variabili conti come token.
Tyilo,

1

C - 4 token

int div3(int x) {
    return ((x * 43) >> 7) * 3 == x;
}

Funziona fino a 383.

Versione precedente (costanti più grandi):

int div3(int x) {
    return ((x * 171) >> 9) * 3 == x;
}

Funziona fino al 1535


1

bash - ???

Non sono sicuro di come segnare questo.

seq 0 85 | awk '{print $1 * 3}' | grep -w [number] | wc -l

per esempio

$ seq 0 85 | awk '{print $1 * 3}' | grep -w 11 | wc -l
0

$ seq 0 85 | awk '{print $1 * 3}' | grep -w 12 | wc -l
1

$seq 0 85 | awk '{print $1 * 3}' | grep -w 254 | wc -l
0

$seq 0 85 | awk '{print $1 * 3}' | grep -w 255 | wc -l
1

1

Befunge 93 - 5 token

Risolto - divisione rimossa.

v      @._1.@
         \   
         0   
         +   
         3   
>&>3-:0\`|   
  ^      <   

Ottiene l'input, continua a sottrarre 3 fino a quando è inferiore a 0, indirizza il puntatore verso l'alto ('|'), quindi aggiunge 3. Se il valore è 0, il puntatore si sposta a destra (" 1. @" genera '1') altrimenti si sposta a sinistra ("@. " genera '0'). '@' termina il programma.


1

Lotto - 7 token

penso

@echo off
for /L %%a in (0,3,%1) do set a=%%a
if %a%==%1 echo 1

Restituisce 1se il numero dato (come stdin) è divisibile per tre.


Sono ammessi loop?
sergiol,

1

Rubino, 6 token (?)

Non sono davvero sicuro di come contare i token. OP, puoi segnarmi?

Penso che sia 6 ... 1, 0, 0, *, 255,x

Si noti che *non è una moltiplicazione intera.

def div3(x)
  ([1,0,0]*255)[x]
end

Un token nel senso del PO non sarebbe solo uno dei precedenti elencati nella domanda?
C5H8NNaO4,

@ C5H8NNaO4 E allora? 0?
Non che Charles, il

@ C5H8NNaO4 forse 4 per le costanti?
Non che Charles, il

1

Python 0

Ho pubblicato un auricolare ma ho usato i condizionali. Ecco per non usare condizionali e token, solo parole chiave

def g(x): return ([[lambda : g(sum(int(y) for y in list(str(x)))),lambda: 0][[False,True].index(x in[0,1,2,4,5,7,8])], lambda: 1][[False,True].index((lambda y: y in[3,6,9])(x))])()

usa il trucco che il multiplo di 3 ha cifre che si sommano a 3

Modifica: rimosso lambda non necessario

def g(x):return([[lambda: g(sum(int(y) for y in list(str(x)))),lambda:0][[False,True].index(x in[0,1,2,4,5,7,8])], lambda:1][[False,True].index(x in[3,6,9])])()

Modifica: golfato ulteriormente (117 caratteri) ancora nessun gettone

exec"g=`x:(((`:g(sum(int(y)for y in str(x)),`:0)[x in[0,1,2,4,5,7,8]],`:1)[x in[3,6,9]])()".replace('`','lambda ')

Accesso diretto ucciso per l'ottimo getitem di Python Più a 132 caratteri

exec"g={0}x:((({0}:g(sum(int(y)for y in str(x))),{0}:0{1}0,1,2,4,5,7,8]),{0}:1{1}3,6,9]))()".format('lambda ',').__getitem__(x in[')

http://www.codeskulptor.org/#user34_uUl7SwOBJb_0.py


[]Tuttavia, l' accesso alla matrice non è consentito.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳


Bene, la domanda non usa la regola nel tag wiki. La domanda ha delle restrizioni sulle operazioni consentite. Nota la parola only.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Beh, è ​​una buona cosa che anche Pitone abbia un attributo nativo per questo
Dylan Madisetti,

0

Python - 25 token

Per iniziare, ho una lunga soluzione che è l'implementazione di una delle risposte nel link nel mio primo post. nè inserito.

a = (n>>7)-((n&64)>>6)+((n&32)>>5)-((n&16)>>4)+((n&8)>>3)-((n&4)>>2)+((n&2)>>1)-(n&1)
print(a==0 or a==3)

orè equivalente a ||.


0

JavaScript - 3 token

Provalo sulla console del tuo browser:

a = prompt().split('');
sum = 0;

do {
  sum = a.reduce(function(p, c) {
     return parseInt(p) + parseInt(c); 
  });

  a = sum.toString().split('');

} while(a.length > 1)

alert([3, 6, 9].indexOf(+sum) > -1)

Come sei arrivato a quella conclusione? Conto circa 37 token.
nyuszika7h,

"Un token è una delle costanti e variabili escluse sopra". Come hai contato 37?
William Barbosa,

1
Oh, capisco. L'OP sembra non essere d'accordo con la pagina informativa di atomic-code-golf .
nyuszika7h,

In realtà, ora non sono sicuro di aver ragione o no. Il mio punteggio sarebbe 70+ in base al violino da golf con codice atomico.
William Barbosa,

1
Il problema non riguarda il numero di token, ma le operazioni che stai utilizzando. Non penso che sono consentiti stringhe, analisi, loop, array, ecc.
aditsu,

0

JavaScript
non è sicuro del token #

function mod3 (i) { return {'undefined':'100','0':'0'}[[0][i]][i.toString (3).split('').pop ()]}

o se l'uscita per 0 può essere 1;

function mod3 (i) { return '100'[i.toString (3).split('').pop ()]}


2
Devo dire che non sono sicuro di quali regole si applichino a questa sfida. Sono consentite chiamate a funzioni e accessi alla proprietà?
C5H8NNaO4,

0

Tcl , 83 byte

proc T n {while \$n>9 {set n [expr [join [split $n ""] +]]};expr {$n in {0 3 6 9}}}

Provalo online!


Outgolf fallito: 96 byte proc T n {set n [expr [join [split [expr [join [split $n ""] +]] ""] +]];expr {$n in {0 3 6 9}}} Provalo online!
sergiol,

Un altro errore: ** 87 byte ** proc T n {expr {[expr [join [split [expr [join [split $n ""] +]] ""] +]] in {0 3 6 9}}} Provalo online!
sergiol
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.