Encuentra un múltiplo de un número dado cuya representación decimal parece binaria

34

Me he encontrado con una pregunta en el sitio de revisión de código que parece interesante. Creo que OP lo está haciendo mal, pero no puedo estar seguro ... ¡Así que vamos a resolverlo por él! (escriba un programa, no una función / procedimiento)

Entrada (stdin o similar):

Un entero xen notación decimal. Es mayor que 1 y menor que 2 ^ 31.

Salida (stdout o similar):

Un entero yen notación decimal. El producto x * yen representación decimal debe contener solo dígitos 0 y 1. Debe ser el número mínimo mayor que 0.

Nota: la salida no está limitada: si el mínimo yes de alrededor de 10 ^ 100, su programa debe generar todos sus 100 dígitos (no sé si hay un límite razonable, como 2 ^ 64, encendido y) no lo resolvió )

Su programa debe finalizar en un tiempo razonable (1 segundo? 1 hora? - algo así) para todos xen el rango.

Prima:

Si su programa no tiene un límite en el tamaño de la entrada (excepto RAM) y tiene una complejidad polinómica, multiplique el conteo de bytes de su programa 0.8y redondee hacia abajo.


Ejemplo: entrada 2; salida 5, porque 2 * 5 = 10

Ejemplo: entrada 21; salida 481, porque 21 * 481 = 10101


Descargo de responsabilidad: no soy responsable de la pregunta en el sitio de revisión de código. En caso de cualquier discrepancia, solo la descripción anterior debe considerarse como la especificación adecuada.

OEIS A079339

anatolyg
fuente
66
Siempre debe ser solucionable. Claramente, debe existir al menos una q tal que haya un número infinito de n tal que 10 ^ n mod x = q. Tome x tales valores de n y sume las potencias respectivas 10 ^ n.
feersum
1
Múltiplos de 9 parecen producir resultados inusualmente altos.
SuperJedi224
1
Problema relacionado con el Proyecto Euler , para cualquiera que pensara que esta pregunta le
resultaba
1
Por complejidad polinómica, ¿quiere decir polinomio en el número de dígitos de la entrada o polinomio en el valor de la entrada?
Reto Koradi
3
@anatolyg mina no es fuerza bruta
aditsu

Respuestas:

8

Pyth, 9 bytes

f!-`*TQ10

Demostración

Para cada múltiplo, conviértalo en una cadena, reste los dígitos 10(usando el práctico int de Pyth para emitir cadenas en este caso) y luego niegue lógicamente el resultado, terminando la búsqueda solo cuando se encuentre el múltiplo correcto.

Solución extra, 10 bytes:

f.xi`*TQ2Z

Esta solución realmente comprueba si la representación de cadena del número puede tratarse como un número binario ( i ... 2) y termina cuando no se produce un error en este intento.

isaacg
fuente
18

Python 2, solución eficiente, 99

n=input()
d={n:0}
k=1
while min(d):[d.setdefault((x+k)%n,d[x]+k)for x in set(d)];k*=10
print d[0]/n

Gracias Sp3000 por algunos consejos de golf.

Reto a todos los demás a publicar (en sus propias respuestas) cuánto tiempo lleva obtener el resultado para la entrada 72o 99:) Si son realmente rápidos, intente algo como el 79992siguiente (todavía <1 segundo aquí).

Explicación:

Pensé que esto no era necesario (ya que el código es bastante legible), pero recibí una solicitud, así que aquí va:

La primera idea es que un número de aspecto binario es una suma de 1 o más potencias diferentes de 10. Por lo tanto, podemos intentar agregar varias potencias de 10 de diferentes maneras hasta obtener el resto 0.

Si lo hacemos ingenuamente, es lo mismo que generar todos los números de aspecto binario y probarlos. Pero muchos restos serán lo mismo. Una mejor manera es registrar solo el número más pequeño que dio un cierto resto, y sucesivamente agregar mayores potencias de 10 a los números que registramos. Eso es lo que hace el programa.

des un diccionario / mapa donde las claves son residuos y los valores son números de aspecto binario con ese resto. La inicial n:0es un caso especial: se supone que es 0:0para que podamos comenzar a agregarle poderes, pero el algoritmo se detiene al encontrar la clave 0, por lo que utilicé en su nlugar, lo que garantiza que tendrá el mismo efecto y no interferirá con los otros valores.

Luego comenzamos a agregar potencias de 10 (almacenadas k) a todos los números existentes y registramos los restantes. Agregamos kal resto: (x+k)%ny al número:, d[x]+ky lo registramos solo si es un resto nuevo d.setdefault(…), luego pasa a la siguiente potencia: k*=10y repite hasta obtener la clave 0:while min(d)

Al final, d[0]da el número de aspecto binario que tiene el resto 0 mod n, por lo que lo dividimos por npara obtener la solución.

Nota: el programa se puede hacer más eficiente evitando grandes números (registrando exponentes en lugar de potencias de 10 y calculando los restos de potencias de valores anteriores), pero es código golf, así que ...

De hecho, aquí, escribí una versión más rápida:

n=input()
d={n:0}
k=1
b=0
while 0not in d:
 for x in list(d):d.setdefault((x+k)%n,b)
 k=(k*10)%n;b+=1
x=10**d[0]
while x%n:x+=10**d[n-x%n]
print x/n
aditsu
fuente
1
Mi respuesta tampoco se entiende. xD "Dangit, Java, ¡maldice tu elección de Integer.MAX_VALUE sobre el uso de BigInteger por defecto!" - Todos los programadores de Java
Addison Crump
@VTCAKAVSMoACE ¿por qué no usas Long?
aditsu
Hmm Es un byte extra, pero ... vale la pena. ¡Gracias!
Addison Crump
O no. Eso realmente lo reduce seriamente. ¡Gracias!
Addison Crump
1
Tiempos para resolver 99: aditsu: 0.001 segundos; xnor: más de 5 horas y aún no se completó.
user193661
13

Python 2, 47 bytes

n=a=input()
while'1'<max(str(a)):a+=n
print a/n

Rastrea el número de entrada ny el múltiplo actual a. Cuando aparece binario, genera la relación a/n. Para verificar que un número esté compuesto por 0'sy 1', comparamos el carácter máximo en su representación de cadena con '1'.

Utiliza en str(a)lugar de `a`evitar largos que terminan en L. Lamentablemente, 'L'es más grande que '1'.

xnor
fuente
12

Perl, 27 bytes

#!perl -p
1while($_*++$\)=~/[2-9]/}{

Contando el shebang como uno, la entrada se toma de stdin.

Uso de muestra

$ echo 2 | perl dec-bin.pl
5

$ echo 21 | perl dec-bin.pl
481

$ echo 98 | perl dec-bin.pl
112245

Perl, 25 bytes

#!perl -p
eval'0b'.++$\*$_||redo}{

Una mejora de dos bytes por @skmrx .

En lugar de verificar con una expresión regular, esto intenta evaluar el producto como un literal binario. Al fallar, pasa al siguiente. Por lo general, la octfunción se usaría para este propósito, pero recorta silenciosamente dígitos no válidos, lo que no es útil en este desafío.


Perl, 40 bytes

#!perl -p
1while($b=sprintf"%b",++$i)%$_;$_=$b/$_

Una solución mucho más eficiente. Repetimos las representaciones binarias, las interpretamos como base 10 y luego verificamos la divisibilidad. Los tiempos de ejecución para todos los valores por debajo de 100 son insignificantes.

Uso de muestra

$ echo 72|perl dec-bin.pl
1543209875

$ echo 99|perl dec-bin.pl
1122334455667789
primo
fuente
2
Bien :) ¡Aprendí un par de cosas nuevas de tu publicación de hoy! Mientras leía su código, encontré una manera de eliminar un par de bytes del primer código:eval"0b".$_*++$\||redo}{
svsd
Pero supongo que tendremos que incluir use bigintpara admitir los grandes números que OP ha ordenado que se
admitan
1
@skmrn Eso es genial. Lo había intentado oct'0b'.++$\*$_, pero recorta silenciosamente dígitos no válidos. No pensé en usar evalen su lugar.
primo
11

Javascript, 43 bytes

Esto terminó mucho más corto de lo que pensaba. Básicamente aumenta yhasta 1 hasta y * (input number) = (binary-looking number). Obviamente bastante ineficiente.

for(x=prompt(y=0);!+('0b'+x*++y););alert(y)


Javascript (solución más eficiente), 53 bytes

Este se incrementa yen binario hasta y / (input number) = (number without a remainder). Entonces sale (number without a remainder).

for(x=prompt(y=1);(z=y.toString(2))%x;y++);alert(z/x)


Javascript (solución aún más eficiente), 76 bytes

Este combina los dos métodos anteriores descritos anteriormente. Comprueba los incrementos yhasta que y * (input number) = (binary-looking number)(lo que significa que la salida es y) O y / (input number) = (number without a remainder)(lo que significa que la salida es (number without a remainder)).

for(x=prompt(y=a=0);!a;a=+('0b'+x*++y)?y:(z=y.toString(2))%x?0:z/x);alert(a)

Mama Fun Roll
fuente
Debería dar 1 cuando sea posible (entrada de ejemplo: 1)
edc65
@ edc65 Corregido, ¡sin cambios en el recuento de bytes!
Mama Fun Roll
Esto bloquea Safari 9.0. Jussayin '. :)
Addison Crump
1
Pero se limita a números pequeños en la producción. Los números Javascript tienen 17 dígitos de precisión, OP está pidiendo algo más grande (y se puede hacer usando aritmética modular)
edc65
Protip: no intente la entrada 72. Firefox 41 se congela durante 15 minutos y luego se bloquea. Descubrí esto de la manera difícil.
ETHproductions
9

Haskell, 72 70 64 60 58 bytes

main=do x<-readLn;print$[y|y<-[1..],all(<'2')$show$x*y]!!0

Editar: @ Jan Dvorak me ayudó a ahorrar 4 bytes.

Editar: @BlackCap guardó 2 bytes cambiando a donotación. ¡Gracias!

nimi
fuente
main=print.f=<<readLn
John Dvorak
Puede guardar un byte al incluir f:main=readLn>>= \x->print$[y|y<-[1..],all(<'2')$show$x*y]!!0
BlackCap
2 en realidadmain=do x<-readLn;print$[y|y<-[1..],all(<'2')$show$x*y]!!0
BlackCap
@BlackCap: ¡Qué bien! ¡Muchas gracias!
nimi
7

Python 2, 67 65 63 60 bytes

a=input();b=1
while set(`a*b`)&set('23456789'):b+=1
print b

¡Gracias a Status por 2 bytes y Shebang por 5 bytes!

Celeo
fuente
1
Creo que debes inicializarb=1
anatolyg
2
Puede reducir 2 bytes haciendoany(c in`a*b`for c in'23456789')
estado
1
No estoy seguro de esto, pero ¿ not c in`a*b`for c in'10'funcionaría?
cole
2
Puede guardar 6 bytes cambiando su condición while a set('a*b')&set('23456789').
Kade
2
`produce un Lpor largos y 'L'>'1'.
user193661
6

JavaScript (ES6) 222 250

Usando matemática de precisión arbitraria (operando en cadenas de dígitos decimales)

Esto se puede jugar un poco más (hecho), pero me gusta el hecho de que no se limita a los números estándar JS (17 dígitos decimales de precisión) y que es rápido.

Pruebe a ejecutar el fragmento a continuación en un navegador compatible con EcmaScript 6. El tiempo es aceptable hasta 9998: no intente con 9999 y sea paciente con 999.

// As a complete program with I/O via popup  
for(n=+prompt(a=[0],q=[t=1]);t;){for(c=1,t=i=0;i<a.length;i++)a[i]=a[i]&c?0:a[i]|c?(c=0,t+=q[i],1):c=0;c&&(a[i]=c,t+=q[i]=q[i-1]*10%n);t%=n}a.reverse().map(a=>(z+=[a],d=z/n|0,z%=n,r||d?r+=d:0),r='',z=0);alert([r,a.join``])

// As a testable function
f=n=>{
  for(a=[0],q=[t=1];t;)
  {
    for(c=1,t=i=0;i<a.length;i++)
      a[i]=a[i]&c?0:a[i]|c?(c=0,t+=q[i],1):c=0
    c&&(a[i]=c,t+=q[i]=q[i-1]*10%n);
    t%=n
  }  
  a.reverse().map(a=>(z+=[a],d=z/n|0,z%=n,r||d?r+=d:0),r='',z=0)
  return [r,a.join``]
}

// Test and timing
out = x => O.innerHTML += x + '\n'

setTimeout(_=>{
;[1,2,10, 21, 23, 98, 72, 9, 99, 999]
.forEach((test,i) => { 
  var t0 = ~new Date  
  var result = f(test)
  out('n='+test+' '+result+' time(ms) ' + (t0-~new Date))
})},100)  
<pre id=O>Timing test cases ...
</pre>

Más legible

Esta es la primera versión, con módulo y división larga como funciones separadas.

// function M - Modulus with arbitrary precision - a is a string of decimal digits
M = (a, b, q = 1, t = 0, j = a.length) => {
  while (j--) + a[j] ? t += q : 0, q = (q * 10) % b;
  return t % b
}

// function D - Long division with arbitrary precision - a is a string of decimal digits
D = (a, b, r = '', z = 0) => [...a].map(a => (z += a, d = z / b | 0, z %= b, r || d ? r += d : 0)) && r

// Testable function 
f = n => {
  for (i = 0; ++i < 1e7 && (z = M(v = i.toString(2), n)););
  return z ? ['big'] : [D(v, n), v]
}
edc65
fuente
Lo hice funcionar en Firefox, pero no parece manejar números más grandes, por ejemplo, 999
aditsu
Tengo una nueva versión que puede manejar 999 en 36 segundos, pero no hay esperanza de llegar a 9999 con el tiempo de espera de JavaScript (cada '9' agregado requiere 2 ^ 9 (~ 500) veces el tiempo para terminar)
edc65
@aditsu es lo mejor que puedo hacer en JavaScript (pero en C # es lo mismo). Siempre esperando una explicación de tu increíble algoritmo
edc65
Agregué
5

Perl, 45 bytes

do{$a++}while($a*($b||=<>))=~/[2-9]/;print$a;
ChicagoRojoSox
fuente
4

PHP, 50 bytes

while(preg_match('/[^01]/',$argv[1]*++$y));echo$y;

Algunos casos de prueba

1 > 1
2 > 5
12 > 925
21 > 481
insertusernamehere
fuente
1
Iba a hacer algo como esto, esto es incluso un poco más corto de lo que tenía en mente
Martijn
4

CJam, 19 17 16 bytes

li:V!{)_V*sAs-}g

Pruébalo en línea

Solución de fuerza bruta, probando valores secuencialmente hasta encontrar uno que cumpla la condición.

La última versión ahorra 2 bytes gracias al uso en Aslugar de "01"crear una cadena que contenga 0y 1, como lo sugiere @aditsu. La solución completa propuesta en el comentario guarda otro byte, pero se ve bastante diferente de la mía, por lo que no quería publicarlo a mi nombre.

Y 1 byte más guardado por @Dennis.

Explicación:

li      Get input and convert to int.
:V      Save it in variable V.
!       Negate the value. Since we saved it in V, we don't need it on the stack anymore.
        But we need 0 on the stack as the start value for y. This conveniently
        accomplishes both with a single operator, since the input is guaranteed to be
        larger than 0.
{       Loop over y.
  )       Increment y.
  _       Copy it.
  V*      Multiply with input in variable V.
  s       Convert to string.
  As      Push the string "10", as the number 10 converted to a string .
  -       Remove 0 and 1 digits. This will result in an empty list if there were only
          0 and 1 digits. The empty list is falsy, and will terminate the loop.
}g      End loop.
Reto Koradi
fuente
3
16:li0{1$+_sAs-}g\/
aditsu
Gracias, @aditsu. Realmente no quería copiar su solución completa bajo mi nombre. Tomé el Aspara construir la cadena, ya que es un cambio muy local, que en retrospectiva (que siempre es mucho más fácil ...) debería haber pensado.
Reto Koradi
1
@RetoKoradi 16 bytes, menos modificaciones: li:V!{)_V*sAs-}gAdemás, 0{)_easi*sAs-}g(15 bytes) funciona con el intérprete de Java y los argumentos de la línea de comandos.
Dennis
4

Python 3 2, 101 76 Bytes

-25 bytes gracias a @aditsu

casi tan eficiente como la solución de @ aditsu

99 -> 0.436 Seconds
72 -> 0.007 Seconds
b,m,n=1,1,input()
while b%n:
 b=int("{0:b}".format(m))
 m+=1
print b/n

En lugar de intentar recorrer los múltiplos en orden creciente, estoy tratando de recorrer los productos, que estoy generando en forma 'binaria'.

Rnet
fuente
No está mal :) ¿Qué pasa con 9999?
aditsu
2
Algunos consejos de golf: use python 2 ( n=input()), while b%n:(inicializar ba 1), sin sangría
aditsu
@aditsu Gracias! 9999 hmmm, parece que tomará un par de días, de vuelta al tablero de dibujo -_-
Rnet
1
bin(m)[2:]debe ser más corto que la cadena de formato. La doble asignación también b=m=1debería ahorrar algunos.
primo
4

Java, 213 bytes

import java.math.*;class P{public static void main(String[]a){BigInteger b=new java.util.Scanner(System.in).nextBigInteger(),c,d=c=b.ONE;while(!(b.multiply(c)+"").matches("[01]+"))c=c.add(d);System.out.print(c);}}

Utiliza BigIntegersy, como tal, tiene (para todos los propósitos y propósitos razonables) un tamaño de entrada ilimitado. Sin embargo, no estoy seguro de la complejidad, eso depende de la tasa de crecimiento de nuestra función aquí.

Gracias a geobits e ypnypn por guardar un puñado de bytes.

SuperJedi224
fuente
Hola, ¿cómo llamarías a esto en tu método principal, por favor?
Probándolo
Tendría que agregar el staticmodificador al método.
SuperJedi224
1
La pregunta dice que la solución debería ser un programa completo, no solo una función.
raznagul
Puede cortar 15 con b.ONEy !(b.multiply(c)+"")(en lugar de toString()).
Geobits
@raznagul: arreglado.
SuperJedi224
4

C, 3675 bytes

Adiós a Code Golf ...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

#define min_n 1
#define max_n 10000

unsigned *mod_list; // list of mods to check
unsigned mod_list_length; // number of mods to check
char *graph; // for each mod, the power of 10 that gives it

void BuildGraph(unsigned n)
{
    unsigned mod10 = 10 % n;
    int pow = 1;

    memset(graph, 0, n);
    if (n == 1)
        return;
    mod_list[0] = 0; // mod 0 - no path coming to it yet
    mod_list[1] = 1; // mod 1 - 10^0 coming to it
    mod_list_length = 2;
    while (graph[0] == 0)
    {
        // We are going to change mod_list_length by adding new nodes.
        // This should not affect the set of nodes we check, so save its old value.
        unsigned mod_list_limit = mod_list_length;
        for (unsigned i = 0; i < mod_list_limit; ++i)
        {
            unsigned mod = mod_list[i] + mod10;
            if (mod >= n)
                mod -= n;
            if (graph[mod] == 0 && mod != 1) // new node?
            {
                graph[mod] = pow; // record the power of 10 with which we come to this node
                mod_list[mod_list_length++] = mod; // add it to the list of nodes
                if (mod == 0) // found the path to 0?
                    return; // stop calculating
            }
        }
        mod10 = (unsigned long long)mod10 * 10 % n; // go to next power of 10
        ++pow;
    }
}

void PrintPath(unsigned n, char *out)
{
    // Going to output powers of 10 in descending order
    unsigned mod = 0; // start at node 0
    int prev_pow = graph[mod] + 1; // happens to be an acceptable initialization
    do {
        int pow = graph[mod];
        while (--prev_pow > pow) // output the proper number of 0-digits
            *out++ = '0';
        *out++ = '1'; // output the digit 1, corresponding to current power of 10
        if (pow == 0)
            break;
        unsigned mod10 = 1;
        for (int p = 0; p < pow; ++p)
            mod10 = (unsigned long long)mod10 * 10 % n;
        mod = (mod + n - mod10 % n) % n; // go to the preceding node
    } while (mod != 0);
    while (--prev_pow >= 0) // output the proper number of 0-digits
        *out++ = '0';
    *out++ = 0;
}

// The long division algorithm
void DivideAndPrint(char *product, unsigned n, FILE* file)
{
    unsigned long long temp = 0;
    int print = 0;
    while (*product != '\0')
    {
        temp = temp * 10 + *product++ - '0';
        if (temp >= n)
            print = 1;
        if (print)
        {
            unsigned quotient = (unsigned)(temp / n);
            unsigned remainder = temp % n;
            fputc('0' + quotient, file);
            temp = remainder;
        }
    }
    fputc('\n', file);
    assert(temp == 0); // if not divisible, there is a bug somewhere
}

void Calc(unsigned n, FILE* file)
{
    char result[99];
    BuildGraph(n);
    PrintPath(n, result);
    DivideAndPrint(result, n, file);
}

int main(int argc, char* argv[])
{
    unsigned n;

    if (argv[1])
    {
        FILE* file = fopen(argv[1], "wt");
        mod_list = calloc(max_n, sizeof(int));
        graph = calloc(max_n, 1);
        clock_t before = clock();
        for (n = min_n; n <= max_n; ++n)
        {
            Calc(n, file);
        }
        clock_t after = clock();
        fprintf(stderr, "Time: %f\n", (after - before) / (double)CLOCKS_PER_SEC);
    }
    else
    {
        scanf("%u", &n);
        mod_list = calloc(n, sizeof(int));
        graph = calloc(n, 1);
        Calc(n, stdout);
    }
}

Ejecutar sin parámetros de línea de comandos - se pone nde stdiny envía el resultado a stdout. Ejecutar con un nombre de archivo: escribe los resultados n = 1...10000en ese archivo y mide el tiempo.

Rendimiento durante 1 ... 10000: 140 ms

Este código utiliza el algoritmo propuesto por aditsu , implementado en C para la velocidad. No hice ningún esfuerzo para jugar golf, por lo que el código sería más fácil de leer.

Lo implementé primero en C ++ usando std::mappara registrar los resultados de la búsqueda, y fue bastante lento. Sin embargo, las teclas de los mapson enteros consecutivos (los llamo mods, porque representan números de módulo n), por lo que es natural usar una matriz, por lo que lo reescribí en C.

Una optimización adicional se refiere a los valores de la asignación: para evitar almacenar un número entero grande para cada uno mod, almaceno solo la potencia más grande de 10 allí; es solo información suficiente para ir a la anterior mod. Entonces, la matriz es realmente un árbol / gráfico de búsqueda. Cuando llega la búsqueda mod = 0, el rastreo de los nodos del árbol hasta la raíz proporciona los poderes de 10 en orden descendente.

Dado que la búsqueda generalmente se detiene bastante rápido, con solo una pequeña fracción de nodos visitados, necesito una lista de nodos activos. Se implementa como una matriz mod_listcon longitud mod_list_length.

Algunas estadísticas de tiempo de ejecución (en una máquina con 16 GB de RAM, lo que parece ser importante para grandes n, porque el programa asigna 5nbytes de memoria):

  • Entrada 99999999- 2 segundos
  • Entrada 999999999- 27 segundos (el resultado es 111111111222222222333333333444444444555555555666666666777777777888888889- probablemente el mayor resultado posible para enteros de 32 bits)
  • Entrada 2147483647- 26 segundos (el resultado es 4661316525084584315813)
  • Entrada 1999999998: 52 segundos (probablemente el mayor tiempo de ejecución posible para enteros de 32 bits)
anatolyg
fuente
2
Entiendo que buscas la recompensa, pero aun así esta es una pregunta de código de golf , y las reglas del sitio requieren que hagas un esfuerzo para desarrollar tu código.
Peter Taylor
Su programa tiene 3546 bytes.
aditsu
@aditsu Medí el recuento de bytes en Windows, que usa el estilo CR / LF
anatolyg
4

C ++ 11, muchos bytes, muy rápido, wow (1.5 s en 1999999998, 0.2 s en 1… 10000)

(Versión de Python Golfed a continuación).

Comenzamos con un concepto similar a la solución de aditsu, donde creamos inductivamente una colección de residuos modulares accesibles en n pasos. Pero en lugar de esperar hasta encontrar el resto 0, verificamos dos restos encontrados a y b de modo que a · 10 ^ n + b = 0. Este enfoque de encuentro en el medio reduce a la mitad la profundidad del árbol de búsqueda, por lo que es mucho más rápido en entradas grandes y usa mucha menos memoria.

Algunos puntos de referencia:

$ echo 99999999 | \time ./decbin
1111111122222222333333334444444455555555666666667777777788888889
0.18user 0.01system 0:00.20elapsed 99%CPU (0avgtext+0avgdata 69360maxresident)k
0inputs+0outputs (0major+16276minor)pagefaults 0swaps
$ echo 999999999 | \time ./decbin
111111111222222222333333333444444444555555555666666666777777777888888889
1.22user 0.04system 0:01.27elapsed 100%CPU (0avgtext+0avgdata 434776maxresident)k
0inputs+0outputs (0major+37308minor)pagefaults 0swaps
$ echo 2147483647 | \time ./decbin
4661316525084584315813
0.00user 0.00system 0:00.01elapsed 72%CPU (0avgtext+0avgdata 5960maxresident)k
0inputs+0outputs (0major+1084minor)pagefaults 0swaps
$ echo 1999999998 | \time ./decbin
555555556111111111666666667222222222777777778333333333888888889444444445
1.42user 0.08system 0:01.50elapsed 100%CPU (0avgtext+0avgdata 544140maxresident)k
0inputs+0outputs (0major+38379minor)pagefaults 0swaps
$ \time ./decbin 10000.out
0.19user 0.00system 0:00.20elapsed 100%CPU (0avgtext+0avgdata 3324maxresident)k
0inputs+264outputs (0major+160minor)pagefaults 0swaps

Código:

#include <algorithm>
#include <boost/iterator/transform_iterator.hpp>
#include <fstream>
#include <list>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

using namespace boost;
using namespace std;

static inline bool cmp_first_partnered(pair<int, pair<int, int>> a,
                                       pair<int, pair<int, int>> b) {
  return a.first < b.first;
}
static inline bool eq_first_partnered(pair<int, pair<int, int>> a,
                                      pair<int, pair<int, int>> b) {
  return a.first == b.first;
}

static pair<int, int> retrace(int modulus, int place, pair<int, int> state,
                              list<vector<int>>::iterator i,
                              list<vector<int>>::iterator j, string &ret) {
  if (i == j)
    return state;
  state = retrace(modulus, (place * 10LL) % modulus, state, next(i), j, ret);
  int remainder = state.first;
  long long k = state.second * 10LL;
  if (!binary_search(i->cbegin(), i->cend(), remainder)) {
    remainder = ((long long)remainder + modulus - place) % modulus;
    k += 1;
  }
  int digit = k / modulus;
  if (digit != 0 || ret.size())
    ret += '0' + digit;
  return make_pair(remainder, k % modulus);
}

static void mult(int modulus, int x, int y,
                 vector<pair<int, pair<int, int>>>::iterator i,
                 vector<pair<int, pair<int, int>>>::iterator j) {
  if (y - x == 1) {
    for (auto k = i; k != j; k++)
      k->first = (k->first * 10LL) % modulus;
    return;
  }

  int z = (x + y) / 2;
  vector<pair<int, pair<int, int>>>::iterator k = lower_bound(
      i, j, make_pair(int(((long long)modulus * z + 9) / 10), make_pair(0, 0)));
  mult(modulus, x, z, i, k);
  mult(modulus, z, y, k, j);
  inplace_merge(i, k, j,
                [](pair<int, pair<int, int>> a, pair<int, pair<int, int>> b) {
                  return make_pair(a.first, a.second.second) <
                         make_pair(b.first, b.second.second);
                });
}

static string go(int modulus) {
  if (modulus == 1)
    return "1";

  int sequence = 1;
  list<vector<int>> v = {{0}};
  vector<pair<int, pair<int, int>>> partnered;
  int place = 1;
  while (true) {
    v.emplace_back(v.rbegin()->size() * 2);
    vector<int> &previous = *next(v.rbegin()), &current = *v.rbegin();

    auto offset = [modulus, place, sequence](int a) {
      return (a + (long long)place) % modulus;
    };
    auto old_mid =
        lower_bound(previous.cbegin(), previous.cend(), modulus - place),
         new_mid = lower_bound(previous.cbegin(), previous.cend(), place);
    current.resize(
        set_union(new_mid, previous.cend(),
                  make_transform_iterator(previous.cbegin(), offset),
                  make_transform_iterator(old_mid, offset),
                  set_union(previous.cbegin(), new_mid,
                            make_transform_iterator(old_mid, offset),
                            make_transform_iterator(previous.cend(), offset),
                            current.begin())) -
        current.begin());

    int place2 = modulus - (long long)place * place % modulus;
    auto offset_partnered = [modulus, place, place2,
                             sequence](pair<int, pair<int, int>> a) {
      return make_pair((a.first + (long long)place2) % modulus,
                       make_pair((a.second.first + (long long)place) % modulus,
                                 sequence + a.second.second));
    };
    auto old_mid_partnered =
        lower_bound(partnered.cbegin(), partnered.cend(),
                    make_pair(modulus - place2, make_pair(0, 0))),
         new_mid_partnered = lower_bound(partnered.cbegin(), partnered.cend(),
                                         make_pair(place2, make_pair(0, 0)));
    vector<pair<int, pair<int, int>>> next_partnered(partnered.size() * 2 + 1);
    auto i =
        set_union(partnered.cbegin(), new_mid_partnered,
                  make_transform_iterator(old_mid_partnered, offset_partnered),
                  make_transform_iterator(partnered.cend(), offset_partnered),
                  next_partnered.begin(), cmp_first_partnered);
    if (new_mid_partnered == partnered.cend() ||
        new_mid_partnered->first != place2)
      *i++ = make_pair(place2, make_pair(place, sequence));
    next_partnered.resize(
        set_union(new_mid_partnered, partnered.cend(),
                  make_transform_iterator(partnered.cbegin(), offset_partnered),
                  make_transform_iterator(old_mid_partnered, offset_partnered),
                  i, cmp_first_partnered) -
        next_partnered.begin());
    partnered.swap(next_partnered);

    sequence += previous.size();

    place = (place * 10LL) % modulus;

    mult(modulus, 0, 10, partnered.begin(), partnered.end());
    partnered.resize(
        unique(partnered.begin(), partnered.end(), eq_first_partnered) -
        partnered.begin());

    auto with_first = [](int a) { return make_pair(a, make_pair(a, 0)); };

    vector<pair<int, pair<int, int>>> hits;
    set_intersection(partnered.cbegin(), partnered.cend(),
                     make_transform_iterator(current.cbegin(), with_first),
                     make_transform_iterator(current.cend(), with_first),
                     back_inserter(hits), cmp_first_partnered);

    if (hits.size()) {
      pair<int, pair<int, int>> best = *min_element(
          hits.begin(), hits.end(),
          [](pair<int, pair<int, int>> a, pair<int, pair<int, int>> b) {
            return a.second.second < b.second.second;
          });
      string ret = "";
      pair<int, int> state =
          retrace(modulus, 1, make_pair(best.second.first, 0), v.begin(),
                  prev(v.end()), ret);
      retrace(modulus, 1, make_pair(best.first, state.second), v.begin(),
              prev(v.end()), ret);
      return ret;
    }
  }
}

int main(int argc, const char *argv[]) {
  ios_base::sync_with_stdio(false);
  if (argc >= 2) {
    ofstream ofs(argv[1]);
    for (int modulus = 1; modulus <= 10000; modulus++)
      ofs << go(modulus) << '\n';
  } else {
    int modulus;
    cin >> modulus;
    cout << go(modulus) << '\n';
  }
  return 0;
}

Python, 280 bytes (8.6 segundos en 1999999998 con PyPy)

n=input()
if n<2:print 1;exit()
d={0:0}
l=[]
k=1
b=x=y=0
while 1:
 for a in[0]+l:
  m=(a+k)%n
  if m not in d:l.append(m);d[m]=b
 k=(k*10)%n;b+=1
 for a in l:
  if(-k*a)%n in d:
   while(a-x)%n:x+=10**d[(a-x)%n]
   while(-y-k*a)%n:y+=10**d[(-y-k*a)%n]
   print(10**b*x+y)/n;exit()
Anders Kaseorg
fuente
2
Entiendo que buscas la recompensa, pero aun así esta es una pregunta de código de golf , y las reglas del sitio requieren que hagas un esfuerzo para desarrollar tu código.
Peter Taylor
1
@PeterTaylor, muy bien, agregué una versión de golf en Python.
Anders Kaseorg
3

Mathematica 115 bytes

p=Drop[Union[FromDigits/@Flatten[Table[Tuples[{0,1},{k}],{k,2,12}],1]],2];
i=Input[];FirstCase[p,x_/;Divisible[x,i]]
DavidC
fuente
3

Java 156 bytes

public class P{public static void main(String[]a){long x=Long.valueOf(a[0]),y;for(y=2;!(""+x*y).replaceAll("1|0","").isEmpty();y++);System.out.println(y);}}

Enormes gracias a aditsu :)

Joba
fuente
No necesita un espacio después [], ypuede ser longdemasiado, olvidó el x*y+""truco en el segundo programa, use en isEmptylugar de verificar la longitud, use en ;lugar de{}
aditsu
De todos modos, bienvenido a code golf :)
aditsu
Debo decir que estoy impresionado, pero hacer y longno acortaría el código
Joba
Sí, lo haría:long x=…,y;
aditsu
ydebe comenzar desde 1, puede inicializarlo en la declaración, su clase no necesita ser pública y puede pasar y++a la x*yparte ( x*y++)
aditsu
2

Pyth - 12 11 bytes

Utiliza un filtro con arg numérico para obtener el primer número natural que cumple el predicado, el valor predeterminado es 1, que es lo que queremos. Setwise diff para verificar si solo ceros y unos.

f!-j*QT10U2

Test Suite .

Maltysen
fuente
Convertir a cadena y eliminar "01. Guarda un personaje.
Jakube
2

R, 45 bytes

x=scan();y=2;while(grepl("[2-9]",x*y))y=y+1;y

Uso:

> x=scan();y=2;while(grepl("[2-9]",x*y))y=y+1;y
1: 2
2: 
Read 1 item
[1] 5
> x=scan();y=2;while(grepl("[2-9]",x*y))y=y+1;y
1: 21
2: 
Read 1 item
[1] 481
> x=scan();y=2;while(grepl("[2-9]",x*y))y=y+1;y
1: 42
2: 
Read 1 item
[1] 2405
plannapus
fuente
2

Java, 198 193 181 bytes

¡Gracias a @aditsu por reducir 5 bytes Y aumentar el rango de números comprobables!

Tenga en cuenta que algunos valores se repiten negativamente debido a cómo Java analiza los enteros. BigInteger podría eludir esto, pero la bonificación era simplemente menos valiosa.

Sé que no voy a ganar, pero espero que esto inspire otras respuestas más cortas.

clase A {public static void main (String [] a) {for (long i = 1 ;; i ++) {try {long b = Long.parseLong (a [0]); if (b * i <0) break; Long.parseLong (b * i + "", 2); System.out.println (i);} catch (Excepción e) {}}}}

Sin relieve:

clase A {
   public static void main (Cadena [] a) {
      for (long i = 1 ;; i ++) {// bucle infinito que comienza en 1
         pruebe {// si se produce un error al intentar analizar como binario, reinicie mientras agrega 1 a i
            largo b = Long.parseLong (a [0]); // Para más tarde: fue más corto declarar que usar dos veces
            si (b * i <0) se rompe; // Salir del programa si hemos hecho un bucle.
            Long.parseLong (b * i + "", 2); // Multiplique y vea si es pasable como un número binario, de lo contrario, arroje el error y regrese al principio del ciclo
            System.out.println (b); // imprimirlo
         } catch (Excepción e) {} // no hacer nada en catch
      }
   }
}
Addison Crump
fuente
2
Es divertido que Longsea ​​más corto que Integer:)
anatolyg
3
La ironía más literal que existe.
Addison Crump
2

C, 107 101 bytes ( 105 99 bytes para 32 bits)

Hay una clara falta de respuestas en C en el código de golf. De hecho, C no es la mejor opción para escribir el programa más pequeño posible, pero no es tan malo:

main(d,b){char s[9];gets(s);for(b=atoi(s);sprintf(s,"%d",b*d),strspn(s,"01")[s];d++);printf("%d",d);}

Puede prescindir de los #incluidos, pero todas las definiciones de funciones serán implícitas. El principal inconveniente es que esto supone que todas las funciones devuelven ints. Este es un problema en máquinas de 64 bits para funciones que realmente devuelven un puntero. Si está en una máquina de 32 bits, se pueden eliminar 2 bytes de la solución anterior:

main(d,b){char s[9];for(b=atoi(gets(s));sprintf(s,"%d",b*d),strspn(s,"01")[s];d++);printf("%d",d);}

Versión algo más legible:

int main()
{
  char s[9];
  gets(s);
  int d = 1;
  int b = atoi(s);
  for (; sprintf(s, "%d", b * d), strspn(s, "01")[s]; d++);
  printf("%d", d);
}
G. Sliepen
fuente
2

Tiempo de C # cerca de 5 segundos (1 a 10000)

Según lo solicitado, aquí hay un programa de golf C # que responde al desafío original. Entrada como argumento de línea de comando, salida a la consola.

using System;using System.Collections.Generic;using System.Numerics;using System.Linq;
class P{static void Main(string[] a){int m,n=int.Parse(a[0]);var d=new Dictionary<int,long>();long b;int h;
for(d[n]=0,b=h=1;;b*=2,h=(h*10)%n)foreach(int k in d.Keys.Reverse())if(!d.ContainsKey(m=(h+k)%n)){
var w=d[k]|b;if(m==0){Console.Write(BigInteger.Parse(Convert.ToString(w,2))/n);return;}d.Add(m,w);}}}

Luego, en cuanto a la recompensa: la recompensa debería ir a aditsu, ya que creo que su algoritmo no puede ser vencido en términos de rendimiento. Pero la respuesta automática de Anatolyg también es sorprendente.

Aquí está mi implementación rápida en C #. Supongo que en C ++ podría ser más rápido (tal vez 2x). Compilado y probado con Visual Studio 2010, .NET framework 4, 64 bits, redirigiendo la salida a nul. Hora: 00: 00: 05.2604315

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
using System.Diagnostics;

class Program
{
   static BigInteger Find(int n)
   {
      var d = new Dictionary<int, long>();
      long kb;
      int km;
      d[n] = 0;
      for (kb = km = 1; ; kb *= 2, km = (km * 10) % n)
      {
         foreach (int key in d.Keys.Reverse())
         {
            int m = (km + key) % n;
            if (!d.ContainsKey(m))
            {
               long w = d[key] | kb;
               if (m == 0)
               {
                  return BigInteger.Parse(Convert.ToString(w, 2));
               }
               d.Add(m, w);
            }
         }
      }
   }

   static void Exec(int n, out string sq, out string sa)
   {
      var v = Find(n);
      sq = (v/n).ToString();
      sa = v.ToString();
   }  

   static void Main(string[] args)
   {
      // string n = Console.ReadLine();
      int limit = int.Parse(args[0]);
      string q ="", a = "";
      Stopwatch x = new Stopwatch();
      x.Start();
      for (int n = 1; n <= limit; n++)
      {
         Exec(n, out q, out a);
         Console.WriteLine("{0} {1} {2}", n, q, a);
      }
      x.Stop();
      Console.Error.WriteLine("{0}", x.Elapsed);
   }
}
edc65
fuente
Tiempos 4.1s. Me equivoqué en la recompensa. Con la última versión de PyPy, la versión más rápida de aditsu es de aproximadamente 8 segundos, por lo que es el doble de rápido.
primo
Entiendo que buscas la recompensa, pero aun así esta es una pregunta de código de golf , y las reglas del sitio requieren que hagas un esfuerzo para desarrollar tu código.
Peter Taylor
No busco la recompensa, es solo un ejemplo de implementación. Pero tienes razón, agregaré una versión de golf.
edc65
@PeterTaylor, ¿podría irse ahora?
edc65
Por cierto, ¿por qué Keys.Reverse? ¿Es importante el orden? Si es solo para evitar problemas de concurrencia, ToListes más corto.
Peter Taylor
2

C con GMP (621 bytes, rápido)

Intenté ser rápido y corto, pero me favoreció rápido. Esta implementación utiliza una versión ligeramente mejorada de la aceleración teórica de números que mencioné en un comentario sobre la respuesta de aditsu .

Guardar como pseudobinary.cy compilar con gcc pseudobinary.c -lgmp -o pseudobinary. Tenga en cuenta que esto asigna tanta memoria para entradas grandes que necesitará compilarla para una plataforma de 64 bits.

#include <gmp.h>
int main(int y,char*z[]){int i,n,b,c,e,f,m,*j,*k,*l,*r,*h;char *d,*s;mpz_t
B,I,Q;i=atoi(z[1]);n=i;for(b=0;n%10<1;++b)n/=10;for(;n%2<1;++b)n/=2;for(;n%5<1;++b)n/=5;if(n<2)--b;d=calloc(n,1);j=calloc(n,sizeof(int));r=calloc(99,sizeof(int));c=2;d[1]=1;*j=r[1]=e=1;l=j+1;for(s=0;!s;++c){r[c]=e=e*10%n;k=l;for(h=j;h<k;h++){f=*h;m=(e+f)%n;if(d[m]<1){*l++=m;if(m<1){s=malloc(99);memset(s,48,99);for(f=c;f;f=d[m=(m+n-r[f])%n])s[c-f]++;s[c]=0;h=k;}d[m]=c;}}}f=strlen(s);s[f]=48;s[f+b]=0;mpz_init_set_str(B,s,10);mpz_init_set_si(I,i);mpz_init(Q);mpz_divexact(Q,B,I);d=mpz_get_str(0,10,Q);printf("%s\n",d);return 0;}

Versión de bucle para temporización (751 bytes)

#include <gmp.h>
char **v;int main(){int i,n,b,c,e,f,m,*j,*k,*l,*r,*h;char *d,*s;mpz_t
B,I,Q;v=calloc(10001,sizeof(char*));v[1]=s=malloc(99);memset(s,48,99);*s=49;s[1]=0;for(i=0;++i<10001;){n=i;for(b=0;n%10<1;++b)n/=10;for(;n%2<1;++b)n/=2;for(;n%5<1;++b)n/=5;d=calloc(n,1);j=calloc(n,sizeof(int));r=calloc(99,sizeof(int));c=2;d[1]=1;*j=r[1]=e=1;l=j+1;for(;!v[n];++c){r[c]=e=e*10%n;k=l;for(h=j;h<k;h++){f=*h;m=(e+f)%n;if(d[m]<1){*l++=m;if(m<1){v[n]=s=malloc(99);memset(s,48,99);for(f=c;f;f=d[m=(m+n-r[f])%n])s[c-f]++;s[c]=0;h=k;}d[m]=c;}}}free(d);free(j);free(r);s=v[n];f=strlen(s);s[f]=48;s[f+b]=0;mpz_init_set_str(B,s,10);mpz_init_set_si(I,i);mpz_init(Q);mpz_divexact(Q,B,I);d=mpz_get_str(0,10,Q);printf("%s\n",d);free(d);s[f+b]=48;s[f]=0;}return 0;}

Versión de bucle sin golf

#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **cache;

int main() {
    int i,n,shift,_kb,km,key,m,*ks,*ksi,*nksi,*res,*ii;
    char *d,*s;
    mpz_t B,I,Q;

    cache = calloc(10001,sizeof(char*));
    if (!cache) { printf("Failed to malloc cache\n"); return 1; }
    cache[1]=s = malloc(99);
    memset(s,48,99);
    *s=49;
    s[1]=0;
    for (i=0;++i<10001;) {
        n=i;
        for(shift=0;n%10<1;++shift)n/=10;
        for(;n%2<1;++shift)n/=2;
        for(;n%5<1;++shift)n/=5;

        d = calloc(n,1);
        if (!d) { printf("Failed to malloc d\n"); return 1; }

        ks = calloc(n,sizeof(int));
        if (!ks) { printf("Failed to malloc ks\n"); return 1; }

        res = calloc(99,sizeof(int));
        if (!res) { printf("Failed to malloc res\n"); return 1; }

        _kb = 2;
        d[1] = 1;
        *ks = res[1] = km = 1;
        nksi = ks + 1;

        for(;!cache[n];++_kb) {
            res[_kb] = km = km*10%n;
            ksi = nksi;
            for (ii = ks; ii < ksi; ii++) {
                key = *ii;
                m = (km + key) % n;
                if (d[m] < 1) {
                    *nksi++ = m;
                    if (m < 1) {
                        cache[n] = s = malloc(99);
                        if (!s) { printf("Failed to malloc s\n"); return 1; }
                        memset(s,48,99);
                        for(key=_kb;key;key = d[m = (m + n - res[key]) % n])s[_kb-key]++;
                        s[_kb]=0;
                        ii = ksi; // break
                    }
                    d[m] = _kb;
                }
            }
        }

        free(d);
        free(ks);
        free(res);

        // Add shift * '0'
        s=cache[n];
        key=strlen(s);
        s[key]=48;
        s[key+shift]=0;

        // convert to big integer, divide, print
        mpz_init_set_str(B,s,10);
        mpz_init_set_si(I,i);
        mpz_init(Q);
        mpz_divexact(Q,B,I);
        d = mpz_get_str(0,10,Q);
        if (!s) { printf("Failed to malloc quotient\n"); return 1; }
        printf("%s\n", d);
        free(d);

        // Remove shift * '0'
        s[key+shift]=48;
        s[key]=0;
    }
    return 0;
}
Peter Taylor
fuente
2

C + GMP, 669

Esto es realmente rápido para números pequeños; comienza a ahogarse cuando el resultado tiene más de 64 dígitos.

#include<gmp.h>
#define B(x)(int)((x*(long)k)%n);
int*M,*H,P[99],n,x,p,q=2,e=1,k=10,y,f,z;char*E,C[99];int b(int k,int t){int
j=E[k],a=1<<(j-2);if(j<2){C[t]=49;return 1;}x=(int)((k+n-P[j]*(long)H[k]%n)%n);if(x)b(x,t);return a+b(H[k],t-a);}int
main(){scanf("%d",&n);E=calloc(n+1,1);M=calloc(n+1,4);H=malloc(n*4);M[1]=E[1%n]=P[1]=1;while(!E[0]){P[++e]=k;p=q;for(x=0;++x<p;){y=B(M[x])if(E[n-y]){E[0]=e;H[0]=M[x];break;}}if(!E[x=0])while(++x<p){y=B(M[x])for(z=0;z<p;++z){f=y+M[z];if(f>=n)f-=n;if(!E[f]){E[f]=e;H[f]=M[x];M[q++]=f;}}}k=B(k)}memset(C,48,98);C[99]=0;x=b(0,97);mpz_t
m,r;mpz_init(r);mpz_init_set_str(m,C+98-x,10);mpz_fdiv_q_ui(r,m,n);puts(mpz_get_str(C,10,r));}

Versión que se repite en 10000 (671 bytes):

#include<gmp.h>
#define B(x)(int)((x*(long)k)%n);
#define N 10001
int M[N],H[N],P[99],n=0,x,p,q,e,k,y,f,z;char E[N],C[99];int b(int k,int t){int
j=E[k],a=1<<(j-2);if(j<2){C[t]=49;return 1;}x=(int)((k+n-P[j]*(long)H[k]%n)%n);if(x)b(x,t);return a+b(H[k],t-a);}int
main(){while(++n<N){memset(E,M[0]=0,n);M[1]=E[1%n]=P[1]=e=1;q=2;k=10;while(!E[0]){P[++e]=k;p=q;for(x=0;++x<p;){y=B(M[x])if(E[n-y]){E[0]=e;H[0]=M[x];break;}}if(!E[x=0])while(++x<p){y=B(M[x])for(z=0;z<p;++z){f=y+M[z];if(f>=n)f-=n;if(!E[f]){E[f]=e;H[f]=M[x];M[q++]=f;}}}k=B(k)}memset(C,48,98);C[99]=0;x=b(0,97);mpz_t
m,r;mpz_init(r);mpz_init_set_str(m,C+98-x,10);mpz_fdiv_q_ui(r,m,n);puts(mpz_get_str(C,10,r));}}

Aquí hay algunos comandos para probar mi código, así como el de mis competidores, y los resultados en mi computadora portátil:

ls -l *.c*       
-rw-r--r-- 1 aditsu aditsu  669 Oct 27 15:01 mult-aditsu-single.c
-rw-r--r-- 1 aditsu aditsu  671 Oct 27 15:01 mult-aditsu.c
-rw-r--r-- 1 aditsu aditsu 3546 Oct 27 15:01 mult-anatoly.c
-rw-r--r-- 1 aditsu aditsu 6175 Oct 27 15:01 mult-anders.cpp
-rw-r--r-- 1 aditsu aditsu  621 Oct 27 15:01 mult-peter-single.c
-rw-r--r-- 1 aditsu aditsu  751 Oct 27 15:01 mult-peter.c

gcc -w -march=native -O3 mult-aditsu-single.c -lgmp -o mult-aditsu-single
gcc -w -march=native -O3 mult-aditsu.c -lgmp -o mult-aditsu
gcc -w -march=native -O3 mult-peter-single.c -lgmp -o mult-peter-single
gcc -w -march=native -O3 mult-peter.c -lgmp -o mult-peter
gcc -w -march=native -O3 --std=c99 mult-anatoly.c -o mult-anatoly
g++ --std=c++11 -march=native -O3 mult-anders.cpp -o mult-anders

for i in {1..5}; do time ./mult-anders mult-anders.txt; done
./mult-anders mult-anders.txt  0.34s user 0.00s system 99% cpu 0.344 total
./mult-anders mult-anders.txt  0.36s user 0.00s system 99% cpu 0.358 total
./mult-anders mult-anders.txt  0.34s user 0.00s system 99% cpu 0.346 total
./mult-anders mult-anders.txt  0.35s user 0.00s system 99% cpu 0.347 total
./mult-anders mult-anders.txt  0.34s user 0.00s system 99% cpu 0.344 total

for i in {1..5}; do ./mult-anatoly mult-anatoly.txt; done
Time: 0.254416
Time: 0.253555
Time: 0.245734
Time: 0.243129
Time: 0.243345

for i in {1..5}; do time ./mult-peter > mult-peter.txt; done
./mult-peter > mult-peter.txt  0.14s user 0.00s system 99% cpu 0.137 total
./mult-peter > mult-peter.txt  0.15s user 0.00s system 97% cpu 0.153 total
./mult-peter > mult-peter.txt  0.15s user 0.00s system 99% cpu 0.149 total
./mult-peter > mult-peter.txt  0.15s user 0.00s system 99% cpu 0.150 total
./mult-peter > mult-peter.txt  0.14s user 0.00s system 99% cpu 0.138 total

for i in {1..5}; do time ./mult-aditsu > mult-aditsu.txt; done
./mult-aditsu > mult-aditsu.txt  0.06s user 0.00s system 95% cpu 0.058 total
./mult-aditsu > mult-aditsu.txt  0.05s user 0.00s system 97% cpu 0.055 total
./mult-aditsu > mult-aditsu.txt  0.06s user 0.00s system 99% cpu 0.056 total
./mult-aditsu > mult-aditsu.txt  0.05s user 0.00s system 99% cpu 0.054 total
./mult-aditsu > mult-aditsu.txt  0.05s user 0.00s system 98% cpu 0.055 total

md5sum *.txt
6eef8511d3bc5769b5d9218be2e00028  mult-aditsu.txt
6eef8511d3bc5769b5d9218be2e00028  mult-anatoly.txt
6eef8511d3bc5769b5d9218be2e00028  mult-anders.txt
6eef8511d3bc5769b5d9218be2e00028  mult-peter.txt
aditsu
fuente
Una respuesta que merece una recompensa. Me interesa especialmente este problema (y su solución inicial), porque es un caso especial del problema de la suma de subconjuntos , que se sabe que es NP completo (dada una lista de los residuos de 10ⁱ mod n , encuentre el primer subconjunto que suma a n ).
primo
@primo Gracias :) Mi enfoque aquí es diferente: doblo el número de dígitos en cada paso en lugar de simplemente aumentarlo, y también verifico primero (muy rápidamente) si alguno de los nuevos números sería una solución, antes de calcular realmente ellos. Y estoy seguro de que todavía hay espacio para jugar al golf.
aditsu
Interesante. Cuando intenté duplicar el número de dígitos en cada paso, terminó siendo más lento. Quizás la verificación previa de soluciones haga una gran diferencia.
Peter Taylor
@PeterTaylor eso es posible ... parece que también estás llamando a calloc en un bucle, lo que podría ralentizarlo. De todos modos, me gustaría agregar una versión no codificada de mi código cuando encuentre algo de tiempo, y también tengo una idea de cómo hacerlo más rápido para números más grandes / desagradables.
aditsu
2

T-SQL, 164 156 155 154 159 bytes

(-1 byte. ¡Gracias Jonathan!)

(-1 más porque ¿por qué tengo espacios finales en las líneas? SMH)

(+5 se dio cuenta de que mi golf rompió cosas)

create function b(@ int)
returns int
as begin
declare @b varchar(max)='',@i int=@
while @>0SELECT @b=cast(@%2 as varchar)+@b,@/=2
return cast(@b as int)/@i
end

No sé por qué sigo volviendo a estas preguntas donde se supone que debo convertir a Binary ... T-SQL no sabe cómo hacerlo bien.

En cualquier caso, aquí hay un SQLFiddle .

Sin golf:

create function binarySquare(@id int)
returns int 
as BEGIN

La mayoría de estas cosas son necesarias para escribir una función en T-SQL, que yo sepa.

    declare @bin nvarchar(max) = ''

Cree una cadena en blanco que vamos a almacenar como nuestro número binario.

    declare @id2 int = @id

Guarde el valor de entrada para usar al final. Parece que debería haber una manera de usar la entrada original incluso si cambiamos el valor, pero no puedo encontrar una.

    while @id>0
      BEGIN
        SET @bin = cast(@id%2 as varchar(1)) + @bin

Entonces tomamos nuestra entrada original, MOD con 2 para encontrar el resto, y ese será nuestro próximo dígito más pequeño. Por ejemplo, 5% 2 = 1

        SET @id = @id/2

Luego tomamos nuestro número y lo dividimos por la mitad. Debido a que es un inttipo, lo redondea al número entero más cercano, por lo que 5/2 = 2. FIN Luego lo recorremos hasta que el valor sea 0. Entonces terminamos con 5% 2 = 1 5/2 = 2 2 % 2 = 0 2/2 = 1 1% 2 = 1 1/2 = 0 que nos da nuestro valor de cadena binaria de 101.

    declare @binNum int = (SELECT cast(@bin as int))

Tomamos nuestra cadena binaria y la convertimos de nuevo en una int.

    return @binNum/@id2

Devolvemos nuestra cadena binaria intdividida por nuestro valor original, según el origen de la pregunta.

END
phroureo
fuente
¿El espacio @>0 SELECTno es omitible?
Jonathan Frech
¡Buena atrapada! Nunca puedo recordar lo que los espacios son capaces de omitir-...
phroureo
La mayoría de las veces puede omitir espacios entre literales y variables / palabras clave, ya que no pueden comenzar con un dígito.
Jonathan Frech
1

Ruby, 46 bytes

Realmente debería eliminar el ciclo while con un ciclo alternativo.

n,k=gets,0;$_="#{n.to_i*k+=1}"while/[^01]/;p k

Editar: ¡Gracias @manatwork por recortar 1 byte!

Edit2: ¡Gracias @histocraft por los locos 9 bytes!

Editar: ¡Gracias @manatwork nuevamente por recortar 7 bytes!

Peter Lenkefi
fuente
z!=z[/[01]+/]Es más corto. z[/[^01]/]Es aún más corto.
manatwork
@manatwork Gracias! ¡1 byte menos!
Peter Lenkefi
2
Los bucles de una sola línea suelen ser los más cortos:z="#{n.to_i*k+=1}"while z[/[^01]/]
histocrático
@histocrat ¡Eso es 9 bytes! Y ni siquiera sabía que Ruby es capaz de esto. ¡Gracias!
Peter Lenkefi
Es interesante que no haya cambiado la prueba al juego de caracteres negado ni después se sugirió la segunda vez. ¿Cualquier razón?
manatwork
1

Scala, 114 bytes

val i=scala.io.StdIn.readInt;Stream.from(1).foreach{x=>if((i*x+"").map{_.asDigit}.max<2){print(x);System.exit(0)}}

Versión legible

val i=scala.io.StdIn.readInt
Stream.from(1).foreach{x => 
    if((i*x+"").map{_.asDigit}.max<2) {
        print(x)
        System.exit(0)
    }
}
wastl
fuente
1

Gawk4 fuerza bruta, 28 + 2 = 30 bytes

{while(++n*$0~/[2-9]/);}$0=n

Necesita ser llamado con la -Mopción de usar números grandes. Por supuesto, esto es ridículamente lento, el uso de grandes números lo ralentiza aún más, pero en teoría la entrada no está limitada y el uso de RAM es insignificante.

Ejemplo de uso (si tiene tiempo que perder ;))

echo 27 | awk -M '{while(++n*$0~/[2-9]/);}$0=n'

gawk4 optimizado, 69 + 2 = 71 bytes

{for(;!a[0];NR*=10)for(i in a)a[j=(s=a[i]+NR)%$0]?0:a[j]=s}$0=a[0]/$0

Bueno, esto terminó siendo un clon de la respuesta de aditsu. Después de mirar esta pregunta , todavía estaba descubriendo cómo codificar la parte de la suma de subconjuntos, cuando no pude resistirme a mirar las otras respuestas aquí.

En awk, los elementos de matriz tienen el comportamiento (¿extraño?) De que si compara un elemento no existente con algo, de alguna manera se inicializa como vacío antes de ser comparado (admito que no estoy muy seguro de lo que está sucediendo allí). Así que después de comprobar !a[0]las for(i in a)salidas de bucle incluso sin inicializar a[$0]a 0como lo hizo aditsu.

Por supuesto, la -Mopción también debe usarse para esto.

Aunque es bastante rápido, sigue siendo notablemente más lento que Python. Para 79992esto toma alrededor de 14 segundos en mi 2GHz Core2Duo. Y no diría que funciona para entradas de hasta 2 ^ 31, porque en el peor de los casos tiene que construir una matriz de números grandes (gawk4 usa GMP para esto), que tiene el tamaño del número de entrada. Como 'bono', las matrices grandes son muy, muy lentas en awk ...

Cabbie407
fuente
1

Dyalog APL , 25

Esto define un programa adecuado "P" (no solo una función sin nombre):

P←2∘{0::⍵∇⍨1+⍺⋄⍺⊣~⍎¨⍕⍺×⍵}

2∘comience con 2 como argumento izquierdo
0::si hay algún error ...
⍵∇⍨1+⍺llámese a sí mismo con un argumento izquierdo incrementado,
⍺×⍵multiplique los argumentos izquierdo y derecho,
haga que la cadena
⍎¨haga que cada carácter sea un
~intento de número lógico NO (si falla, vaya al manejo de errores anterior, de lo contrario ...)
⍺⊣devuelve el argumento izquierdo actual.

      P 2
50
      P 21
481
      P¨⍳8    ⍝ 1 through 8
10 5 37 25 2 185 143 125
Adán
fuente