Determinar si un entero es divisible por 3

20

Su objetivo es determinar si un número es divisible por 3 sin usar condicionales. La entrada será un número de 8 bits sin signo de 0 a 255. ¡Se fomenta la creatividad!

SÓLO tienes permitido usar

  • Igualdad / desigualdad ( ==, !=, >, <, >=, <=)

  • Aritmética ( +, -, x)

  • Operadores lógicos ( !no, &&y, || o)

  • Los operadores bit a bit ( ~no, &y, |o, ^xor, <<, >>, >>>izquierda aritmética y lógica y desplazamientos a la derecha)

  • Constantes (sería mejor si mantuvieras estos pequeños)

  • Asignación variable

Salida 0si es falso, 1si es verdadero.

Se aplican las normas estándar de código de golf atómico. Si tienes alguna pregunta por favor déjala en los comentarios. Métodos de ejemplo aquí . Un token es cualquiera de las constantes y variables excluidas anteriormente.

qwr
fuente
@GregHewgill Mi error tipográfico, debe ser un número de 8 bits.
qwr
2
¿Solo se nos permite usar los operadores anteriores? De lo contrario, el módulo lo haría demasiado fácil.
Jwosty
Además, ¿qué tal la búsqueda de tablas?
Greg Hewgill
3
¿Puedes aclarar lo que quieres decir con no condicionales? ¿Se limita a las declaraciones IF o se aplica también a cosas como bucles?
Ruslan
1
@Ruslan Solo se le permite usar lo anterior.
qwr

Respuestas:

31

C - 2 fichas

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

Parece funcionar hasta 2 31 -1.

Créditos a zalgo("nhahtdh")para la idea inversa multiplicativa.

aditsu
fuente
1
+1. Estaba un poco desconcertado sobre cómo <=funciona, y recordó que 0xAAAAAAAB se toma como unsigned inttipo, por lo que el resultado de la multiplicación no tiene signo.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Los operadores de desigualdad de @DigitalTrauma están permitidos, no prohibidos
aditsu
@aditsu ¡Vaya! ¡Necesito leer más cuidadosamente a veces! +1 gran respuesta!
Trauma digital
@aditsu, lo siento, soy novato, ¿cómo funciona esto exactamente?
Kartik_Koro
2
@Kartik_Koro 0xAAAAAAAB * 3 == 1 debido al desbordamiento, por lo que para cualquier int x, x * 0xAAAAAAAB * 3 == x. Además, y * 3 tiene diferentes valores para diferentes y, por lo tanto, y = x * 0xAAAAAAAB debe ser el único y tal que y * 3 == x. Si x es un múltiplo de 3, y debe ser x / 3, de lo contrario, debe estar funcionando a través del desbordamiento. Una forma simple de verificar es comparar y con x. Ver también en.wikipedia.org/wiki/Modular_multiplicative_inverse
aditsu
17

Python, 3 2 fichas

Solución de fuerza bruta, pero funciona.

0x9249249249249249249249249249249249249249249249249249249249249249>>x&1

Gracias a Howard por la reducción de 1 ficha.

Greg Hewgill
fuente
¡Guauu! Su solución es probablemente la más corta (3 tokens), pero también quiero alentar otras respuestas.
qwr
11
Hay incluso una solución testigo 2: 0x9......>>x&1.
Howard
6

C - 5 4 fichas (?)

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

Funciona para cualquier número de 32 bits sin signo .

Este código hace uso del módulo inverso multiplicativo 2 32 de un divisor para convertir la operación de división en operación de multiplicación.

Editar

Mi solución (publicada 2 minutos después) tiene el mismo espíritu que la solución de aditsu. Crédito a él por el uso de== eso mejora mi solución en 1 token.

Referencia

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
fuente
1
Esto es increíble. Sabía acerca de los números mágicos del famoso truco de raíz cuadrada inversa, pero no sabía que podría usarse para un divisor arbitrario. Esto es Bull: P
qwr
Sí, 0xAAAAAAAB = (2 ^ 33 + 1) / 3 y 171 = (2 ^ 9 + 1) / 3. Escogí la constante más pequeña que hace el truco. Hmm, en realidad también parece funcionar con 86 = (2 ^ 8 + 2) / 3
aditsu
Ratas, incluso 43 = (2 ^ 7 + 1) / 3 funciona, no estoy seguro de cómo me lo perdí. Editado ahora.
aditsu
4

C - 15 fichas (?)

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;
}

Como 4 ≡ 1 (mod 3), tenemos 4 n ≡ 1 (mod 3). La regla de suma de dígitos no se limita a sumar los dígitos, sino que también nos permite dividir arbitrariamente el número en secuencias de dígitos y sumarlos todos manteniendo la congruencia.

Un ejemplo en base 10, divisor = 9:

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

Todas las declaraciones en el programa hacen uso de esta propiedad. En realidad, se puede simplificar a un bucle que ejecuta la declaración n = (n & 0x3) + (n >> 2);hasta n < 4, ya que la declaración simplemente rompe el número en base-4 en el dígito menos significativo y suma las 2 partes.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
fuente
+1: curiosamente, esto funciona para n hasta 512 (en realidad n = 590), pero no estoy muy seguro de por qué.
Paul R
@PaulR: No funcionará para números más grandes debido al transporte (tenga en cuenta que usé la suma en el cálculo). También tenga en cuenta las líneas repetidas.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Sí, no estoy seguro de por qué funciona para valores de 9 bits, ya que solo parece estar probando 8 bits.
Paul R
para números de 9 bits después de la primera adición, se convierte en un máximo de 5 bits, después de la primera, n = (n & 0x3) + (n >> 2);el resultado se reduce a 3 bits y la repetición provocó que permaneciera solo 2 bits stackoverflow.com/a/3421654/995714
phuclv
1
Oh, he cometido un error. Un número de 5 bits + un número de 4 bits puede dar como resultado un número de 6 bits. Pero si n <= 588 sumando los 4 bits superiores y los 2 bits inferiores de ese número de 6 bits, se obtiene una suma de solo 4 bits. Nuevamente agregando eso resulta en un número de 2 bits. 589 y 590 dan como resultado 3 bits en la última suma pero, por cierto, no son divisibles por 3, por lo que el resultado es correcto
phuclv
2

Python (¿2 tokens?)

1&66166908135609254527754848576393090201868562666080322308261476575950359794249L>>x

O

1&0x9249249249249249249249249249249249249249249249249249249249249249L>>x

O

1&0b1001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001>>x
ɐɔıʇǝɥʇuʎs
fuente
2
Duplicado del comentario de Howard
aditsu
@aditsu ... ¿Grandes mentes piensan igual? Juro que no vi eso antes de publicar esto.
23ıʇǝɥʇuʎs
2

JavaScript: 3 tokens

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

Esto abusa del hecho de que el uso de operadores bit a bit en un número lo trunca a un entero en JavaScript.

Tyilo
fuente
Debe ser de 4 fichas: =, *, |,==
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳
1
No creo que la asignación variable cuente como un token.
Tyilo
1

C - 4 fichas

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

Funciona hasta 383.

Versión anterior (constantes más grandes):

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

Funciona hasta 1535

aditsu
fuente
1

bash - ???

No estoy seguro de cómo calificar esto.

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

p.ej

$ 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

fuente
1

Befunge 93: 5 fichas

Corregido - división eliminada.

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

Obtiene la entrada, sigue restando 3 hasta que es menor que 0, dirige el puntero hacia arriba ('|'), luego agrega 3. Si el valor es 0, el puntero se mueve hacia la derecha (" 1. @" genera '1') de lo contrario se mueve hacia la izquierda ("@. " genera '0'). '@' finaliza el programa.

AndoDaan
fuente
1

Lote - 7 fichas

Yo creo que

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

Devuelve 1si el número dado (como stdin) es divisible por tres.

carne sin carne
fuente
¿Están permitidos los bucles?
sergiol
1

Rubí, 6 fichas (?)

Realmente no estoy seguro de cómo contar fichas. OP, ¿puedes anotarme?

Creo que es 6 ... 1, 0, 0, *,255 ,x

Tenga en cuenta que *no es una multiplicación entera.

def div3(x)
  ([1,0,0]*255)[x]
end
No es que Charles
fuente
¿No sería un token en el sentido del OP solo uno de los mencionados en la pregunta?
C5H8NNaO4
@ C5H8NNaO4 ¿Y qué? 0?
No es que Charles
@ C5H8NNaO4 tal vez 4 para constantes?
No es que Charles
1

Python 0

Publiqué Eariler pero usé condicionales. Esto es para usar sin condicionales y sin tokens, solo palabras clave

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 el truco de que múltiples de 3 tienen dígitos que suman 3

Editar: eliminado lambda innecesaria

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])])()

Editar: Golfed más (117 caracteres) todavía sin fichas

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 ')

Matado acceso directo para ingenioso del pitón GetItem más largo en 132 Char

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

Dylan Madisetti
fuente
Sin []embargo, el acceso de matriz no está permitido.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
¿Es? Después de estas reglas, codegolf.stackexchange.com/tags/atomic-code-golf/info
Dylan Madisetti
Bueno, la pregunta no usa la regla en la etiqueta wiki. La pregunta tiene restricciones en las operaciones permitidas. Tenga en cuenta la palabra only.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Bueno, es bueno que Python tenga un atributo nativo para eso también
Dylan Madisetti
0

Python - 25 fichas

Para comenzar, tengo una solución larga que es una implementación de una de las respuestas en el enlace de mi primera publicación. nes entrada.

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)

ores equivalente a ||.

qwr
fuente
0

JavaScript - 3 tokens

Pruébelo en la consola de su navegador:

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)
William Barbosa
fuente
¿Cómo llegaste a esa conclusión? Cuento unos 37 tokens.
nyuszika7h
"Un token es cualquiera de las anteriores excluyendo constantes y variables". ¿Cómo contabas 37?
William Barbosa
1
Oh ya veo. El OP parece estar en desacuerdo con la página de información de atomic-code-golf .
nyuszika7h
En realidad, ahora no estoy seguro de si tengo razón o no. Mi puntuación sería de más de 70 según el violín de golf del código atómico.
William Barbosa
1
El problema no se trata de la cantidad de tokens, sino de las operaciones que está utilizando. No creo que toString, parseInt, bucles, arrays, etc. estén permitidos.
aditsu
0

JavaScript
no está seguro sobre el token #

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

o si se permite que la salida para 0 sea 1;

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

C5H8NNaO4
fuente
2
Tengo que decir que no estoy seguro de qué reglas se aplican a este desafío. ¿Se permiten llamadas a funciones y accesos de propiedad?
C5H8NNaO4
0

Tcl , 83 bytes

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

Pruébalo en línea!

sergiol
fuente
Outgolf fallido: 96 bytes ¡ proc T n {set n [expr [join [split [expr [join [split $n ""] +]] ""] +]];expr {$n in {0 3 6 9}}} Pruébelo en línea!
sergiol
Otro error: ** 87 bytes ** proc T n {expr {[expr [join [split [expr [join [split $n ""] +]] ""] +]] in {0 3 6 9}}} Pruébelo en línea!
sergiol