Temukan kelipatan dari angka tertentu yang representasi desimalnya tampak seperti biner

34

Saya telah menemukan pertanyaan di situs Tinjauan Kode yang sepertinya menarik. Saya pikir OP salah, tapi tidak bisa memastikan ... Jadi mari kita selesaikan untuknya! (menulis program, bukan fungsi / prosedur)

Input (stdin atau serupa):

Integer xdalam notasi desimal. Ini lebih besar dari 1 dan kurang dari 2 ^ 31.

Output (stdout atau serupa):

Integer ydalam notasi desimal. Produk x * ydalam representasi desimal hanya boleh mengandung angka 0 dan 1. Harus minimal jumlah tersebut lebih besar dari 0.

Catatan: output tidak terbatas - jika minimalnya ysekitar 10 ^ 100, program Anda harus mengeluarkan semua 100 digitnya (saya tidak tahu apakah ada batas yang masuk akal, seperti 2 ^ 64, aktif y- tidak menyelesaikannya ).

Program Anda harus selesai dalam waktu yang wajar (1 detik? 1 jam? - sesuatu seperti itu) untuk semua yang ada xdalam jangkauan.

Bonus:

Jika program Anda tidak memiliki batasan ukuran input (kecuali RAM), dan memiliki kompleksitas polinomial, gandakan jumlah byte program Anda dengan 0.8dan bulatkan.


Contoh: Input 2; output 5, karena 2 * 5 = 10

Contoh: Input 21; output 481, karena 21 * 481 = 10101


Penafian: Saya tidak bertanggung jawab atas pertanyaan di situs Tinjauan Kode. Dalam hal terjadi perbedaan, hanya uraian di atas yang harus dianggap sebagai spesifikasi yang tepat.

OEIS A079339

anatolyg
sumber
6
Itu harus selalu bisa dipecahkan. Jelas harus ada setidaknya satu q sedemikian sehingga ada jumlah tak terbatas n sedemikian sehingga 10 ^ n mod x = q. Ambil x nilai n tersebut dan tambahkan bersama kekuatan masing-masing 10 ^ n.
feersum
1
Kelipatan 9 tampaknya menghasilkan hasil yang sangat tinggi.
SuperJedi224
1
Masalah terkait Proyek Euler , bagi siapa pun yang mengira pertanyaan ini tampak familier
Sp3000
1
Dengan kompleksitas polinomial, maksud Anda polinomial dalam jumlah digit input, atau polinomial dalam nilai input?
Reto Koradi
3
@anatolyg punyaku tidak kasar
aditsu

Jawaban:

8

Pyth, 9 byte

f!-`*TQ10

Demonstrasi

Untuk setiap kelipatan, konversikan ke string, kurangi digit dalam 10(menggunakan Pyth's int berguna untuk str cast dalam kasus ini) dan kemudian secara logis meniadakan hasilnya, mengakhiri pencarian hanya ketika kelipatan yang benar ditemukan.

Solusi bonus, 10 byte:

f.xi`*TQ2Z

Solusi ini benar-benar memeriksa apakah representasi string dari angka dapat diperlakukan sebagai angka biner ( i ... 2) dan berakhir ketika kesalahan tidak dilemparkan pada upaya ini.

isaacg
sumber
18

Python 2, solusi efisien, 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

Terima kasih Sp3000 untuk beberapa tips golf.

Saya menantang semua orang untuk memposting (dalam jawaban mereka sendiri) berapa lama untuk mendapatkan hasil untuk input 72atau 99:) Jika itu benar-benar cepat, coba sesuatu seperti yang 79992berikutnya (masih <1 detik di sini).

Penjelasan:

Saya pikir ini tidak perlu (karena kode ini cukup mudah dibaca), tapi saya mendapat permintaan, jadi begini:

Gagasan pertama adalah bahwa angka yang tampak biner adalah jumlah dari 1 atau lebih dari 10 kekuatan yang berbeda. Oleh karena itu, kita dapat mencoba menambahkan berbagai kekuatan 10 dengan cara yang berbeda sampai kita mendapatkan sisa 0.

Jika kita melakukannya secara naif, itu sama dengan menghasilkan semua angka yang tampak biner dan mengujinya. Tetapi banyak sisa yang akan sama. Cara yang lebih baik adalah mencatat hanya angka terkecil yang memberikan sisa tertentu, dan berturut-turut menambahkan kekuatan 10 yang lebih besar ke angka yang kami rekam. Itulah yang dilakukan oleh program ini.

dadalah kamus / peta di mana kunci adalah sisa dan nilai adalah angka yang tampak biner dengan sisanya. Inisial n:0adalah kasus khusus: seharusnya 0:0jadi kita dapat mulai menambahkan kekuatan untuk itu, tetapi algoritma berhenti ketika menemukan kunci 0, jadi saya menggunakan nsebaliknya, yang dijamin memiliki efek yang sama dan tidak mengganggu nilai-nilai lainnya.

Kemudian kami mulai menambahkan kekuatan 10 (disimpan dalam k) ke semua nomor yang ada dan merekam sisanya. Kami menambah ksisanya: (x+k)%ndan ke nomor d[x]+k:, dan merekamnya hanya jika itu adalah sisa baru:, d.setdefault(…)kemudian pergi ke kekuatan berikutnya: k*=10dan ulangi sampai kami mendapatkan kunci 0:while min(d)

Pada akhirnya, d[0]berikan angka yang tampak biner yang memiliki sisa 0 mod n, jadi kami membaginya dengan nuntuk mendapatkan solusinya.

Catatan: program ini dapat dibuat lebih efisien dengan menghindari sejumlah besar (merekam eksponen daripada kekuatan 10, dan menghitung sisa kekuatan dari nilai sebelumnya), tetapi kode golf, jadi ...

Bahkan, di sini, saya menulis versi yang lebih cepat:

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
sumber
1
Jawaban saya juga tidak. xD "Sialan, Java, mengutuk Integer.MAX_VALUE pilihan Anda menggunakan BigInteger secara default!" - Every Java Programmer Ever
Addison Crump
@VTCAKAVSMoACE, mengapa Anda tidak menggunakan Long?
aditsu
Hmm. Ini byte tambahan, tapi ... sepadan. Terima kasih!
Addison Crump
Atau tidak. Itu benar-benar serius menguranginya. Terima kasih!
Addison Crump
1
Pengaturan waktu untuk menyelesaikan 99: aditsu: 0,001 detik; xnor: 5+ jam dan masih belum selesai.
user193661
13

Python 2, 47 byte

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

Melacak nomor input ndan multiple saat ini a. Ketika aterlihat seperti biner, hasilkan rasio a/n. Untuk memeriksa apakah suatu angka terbuat dari 0dan 1, kita membandingkan karakter maksimum dalam representasi stringnya dengan '1'.

Penggunaan str(a)bukannya `a`menghindari jangka waktu yang berakhir dengan L. Sayangnya, 'L'lebih besar dari '1'.

Tidak
sumber
12

Perl, 27 byte

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

Menghitung shebang sebagai satu, input diambil dari stdin.

Contoh Penggunaan

$ echo 2 | perl dec-bin.pl
5

$ echo 21 | perl dec-bin.pl
481

$ echo 98 | perl dec-bin.pl
112245

Perl, 25 byte

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

Peningkatan dua byte oleh @skmrx .

Alih-alih memeriksa terhadap suatu regex, ini malah mencoba untuk mengevaluasi produk sebagai literal biner. Setelah gagal, ia beralih ke yang berikutnya. Biasanya octfungsi tersebut akan digunakan untuk tujuan ini, tetapi fungsi ini diam-diam memotong angka yang tidak valid, yang tidak berguna dalam tantangan ini.


Perl, 40 byte

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

Solusi yang jauh lebih efisien. Kami beralih dari representasi biner, menafsirkannya sebagai basis 10, dan kemudian memeriksa keterbagiannya. Runtime untuk semua nilai di bawah 100 dapat diabaikan.

Contoh Penggunaan

$ echo 72|perl dec-bin.pl
1543209875

$ echo 99|perl dec-bin.pl
1122334455667789
primo
sumber
2
Bagus :) Saya belajar beberapa hal baru dari posting Anda hari ini! Saat membaca kode Anda, saya menemukan cara untuk memotong beberapa byte dari kode pertama:eval"0b".$_*++$\||redo}{
svsd
Tapi saya kira kita harus memasukkan use bigintuntuk mendukung sejumlah besar yang telah diamanatkan OP untuk didukung :(
svsd
1
@ skmrn Itu brilian. Saya sudah mencoba oct'0b'.++$\*$_, tetapi diam-diam memotong angka yang tidak valid. Saya tidak berpikir untuk menggunakannya evalsebagai gantinya.
primo
11

Javascript, 43 byte

Ini akhirnya jauh lebih pendek dari yang saya kira. Ini pada dasarnya meningkatkan yhingga 1 y * (input number) = (binary-looking number). Jelas sangat tidak efisien.

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


Javascript (solusi yang lebih efisien), 53 byte

Yang satu ini bertambah ydalam biner hingga y / (input number) = (number without a remainder). Maka itu output (number without a remainder).

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


Javascript (solusi yang lebih efisien), 76 byte

Yang ini menggabungkan kedua metode sebelumnya yang dijelaskan di atas. Ia memeriksa kenaikan ysampai salah satu y * (input number) = (binary-looking number)(artinya outputnya y) ATAU y / (input number) = (number without a remainder)(artinya outputnya (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
sumber
Ini harus memberikan 1 bila memungkinkan (contoh input: 1)
edc65
@ edc65 Tetap - tanpa perubahan dalam jumlah byte!
Mama Fun Roll
Ini membuat Safari 9.0 mogok. Jussayin '. :)
Addison Crump
1
Tapi itu terbatas pada angka kecil dalam output. Nomor Javascript memiliki 17 digit presisi, OP meminta sesuatu yang lebih besar (dan dapat dilakukan dengan menggunakan aritmatika modular)
edc65
Protip: Jangan coba masukan 72. Firefox 41 macet selama 15 menit dan kemudian macet. Saya menemukan ini dengan cara yang sulit.
ETHproduksi
9

Haskell, 72 70 64 60 58 byte

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

Sunting: @Jan Dvorak membantu saya menghemat 4 byte.

Sunting: @BlackCap menyimpan 2 byte dengan beralih ke donotasi. Terima kasih!

nimi
sumber
main=print.f=<<readLn
John Dvorak
Anda dapat menyimpan byte dengan cara inlining f:main=readLn>>= \x->print$[y|y<-[1..],all(<'2')$show$x*y]!!0
BlackCap
2 sebenarnyamain=do x<-readLn;print$[y|y<-[1..],all(<'2')$show$x*y]!!0
BlackCap
@ BlackCap: Bagus! Terima kasih banyak!
nimi
7

Python 2, 67 65 63 60 byte

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

Berkat Status untuk 2 byte dan Shebang untuk 5 byte!

Celeo
sumber
1
Saya pikir Anda harus menginisialisasib=1
anatolyg
2
Anda dapat mencukur 2 byte dengan melakukanany(c in`a*b`for c in'23456789')
Status
1
Saya tidak yakin tentang ini tetapi apakah akan not c in`a*b`for c in'10'berhasil?
cole
2
Anda dapat menyimpan 6 byte dengan mengubah kondisi while Anda menjadi set('a*b')&set('23456789').
Kade
2
`menghasilkan Ljangka panjang dan 'L'>'1'.
user193661
6

JavaScript (ES6) 222 250

Menggunakan matematika presisi arbitrer (beroperasi pada string angka desimal)

Ini bisa bermain golf sedikit lebih (selesai), tapi saya suka fakta bahwa itu tidak terbatas pada angka standar JS (17 digit desimal presisi) dan cepat.

Tes menjalankan cuplikan di bawah ini di peramban yang mendukung EcmaScript 6. Waktu dapat diterima hingga 9998 - jangan coba 9999 dan bersabarlah dengan 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>

Lebih mudah dibaca

Ini adalah versi pertama, dengan modulus dan pembagian panjang sebagai fungsi yang terpisah.

// 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
sumber
Saya dapat menggunakannya di Firefox, tetapi sepertinya tidak menangani angka yang lebih besar, misalnya 999
aditsu
Saya memiliki versi baru yang dapat menangani 999 dalam 36 detik, tetapi tidak ada harapan untuk mencapai 9999 dengan batas waktu javascript (setiap '9' yang ditambahkan memerlukan 2 ^ 9 (~ 500) kali waktu untuk menyelesaikannya)
edc65
@aditsu itu yang terbaik yang bisa saya lakukan dalam JavaScript (tetapi dalam C # itu cukup sama). Eaherly menunggu penjelasan tentang Anda algoritma yang luar biasa
edc65
Saya menambahkan penjelasan sekarang
aditsu
5

Perl, 45 byte

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

Pyth, 10 byte

f<eS`*TQ`2

Jalankan kodenya.

Sebuah port jawaban Python saya , mengambil dari Maltysen penggunaan funtuk menemukan angka positif pertama yang memenuhi syarat.

Tidak
sumber
4

PHP, 50 byte

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

Beberapa test case

1 > 1
2 > 5
12 > 925
21 > 481
masukkan nama pengguna di sini
sumber
1
Apakah akan membuat sesuatu seperti ini, ini bahkan sedikit lebih pendek daripada yang saya pikirkan
Martijn
4

CJam, 19 17 16 byte

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

Cobalah online

Solusi brute force, mencoba nilai secara berurutan sampai satu kali memenuhi kondisi ditemukan.

Versi terbaru menghemat 2 byte karena menggunakan Asalih-alih "01"membangun string yang mengandung 0dan 1, seperti yang disarankan oleh @aditsu. Solusi lengkap yang diusulkan dalam komentar menyimpan byte lain, tetapi terlihat cukup berbeda dari milik saya, jadi saya tidak ingin mempostingnya di bawah nama saya.

Dan 1 byte lagi disimpan oleh @ Dennis.

Penjelasan:

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
sumber
3
16:li0{1$+_sAs-}g\/
aditsu
Terima kasih, @aditsu. Saya tidak benar-benar ingin menyalin solusi lengkap Anda dengan nama saya. Saya memang mengambil Asuntuk membangun string, karena itu adalah perubahan yang sangat lokal, yang di belakang (yang selalu jauh lebih mudah ...) Saya seharusnya memikirkan.
Reto Koradi
1
@RetoKoradi 16 byte, kurang modifikasi: li:V!{)_V*sAs-}gJuga, 0{)_easi*sAs-}g(15 byte) berfungsi dengan interpreter Java dan argumen baris perintah.
Dennis
4

Python 3 2, 101 76 Bytes

-25 byte terima kasih kepada @aditsu

hampir seefisien solusi @ 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

Alih-alih mencoba untuk mengulang melalui kelipatan dalam urutan meningkat, saya mencoba untuk mengulang melalui produk, yang saya hasilkan dalam bentuk 'biner'.

Rnet
sumber
Tidak buruk :) Bagaimana dengan 9999?
aditsu
2
Beberapa kiat bermain golf: gunakan python 2 ( n=input()), while b%n:(inisialisasi bke 1), tanpa lekukan
aditsu
@aditsu Terima kasih! 9999 hmmm, sepertinya butuh beberapa hari, kembali ke papan gambar -_-
Rnet
1
bin(m)[2:]harus lebih pendek dari string format. Tugas ganda pada b=m=1harus menyimpan beberapa juga.
Primo
4

Java, 213 byte

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

Penggunaan BigIntegerdan karenanya memiliki (untuk semua maksud dan tujuan yang masuk akal) ukuran input tidak terbatas. Namun, tidak yakin tentang kerumitannya, itu tergantung pada tingkat pertumbuhan fungsi kami di sini.

Terima kasih kepada geobits dan ypnypn karena telah menyimpan beberapa byte.

SuperJedi224
sumber
Hai, bagaimana Anda menyebutnya dengan metode utama? Mencoba tetapi tidak berhasil
Yassin Hajaj
Anda harus menambahkan staticpengubah ke metode.
SuperJedi224
1
Pertanyaannya mengatakan bahwa solusinya harus berupa program yang lengkap, bukan hanya fungsi.
raznagul
Anda dapat memotong 15 dengan b.ONEdan !(b.multiply(c)+"")(bukan toString()).
Geobits
@raznagul: Diperbaiki.
SuperJedi224
4

C, 3675 byte

Begitu lama untuk 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);
    }
}

Jalankan tanpa parameter baris perintah - didapat ndari stdindan menampilkan hasilnya stdout. Jalankan dengan nama file - ia menulis hasilnya ke n = 1...10000dalam file itu, dan mengukur waktu.

Kinerja untuk 1 ... 10000: 140 ms

Kode ini menggunakan algoritma yang diusulkan oleh aditsu , diimplementasikan dalam C untuk kecepatan. Saya tidak berusaha untuk membuatnya, jadi kode ini akan lebih mudah dibaca.

Saya menerapkannya pertama kali di C ++ menggunakan std::mapuntuk merekam hasil pencarian, dan itu agak lambat. Namun, kunci-kunci mapbilangan bulat adalah berurutan (saya menyebutnya mods, karena mereka mewakili angka modulo n), jadi wajar jika menggunakan array - jadi saya menulis ulang dalam C.

Optimalisasi tambahan menyangkut nilai-nilai pemetaan - untuk menghindari menyimpan bilangan bulat besar untuk masing-masing mod, saya hanya menyimpan kekuatan terbesar dari 10 di sana - itu hanya cukup informasi untuk pergi ke sebelumnya mod. Jadi array ini benar-benar pohon pencarian / grafik. Ketika pencarian tiba mod = 0, melacak node pohon kembali ke root memberikan kekuatan 10 dalam urutan menurun.

Karena pencarian biasanya berhenti agak cepat, dengan hanya sebagian kecil dari node yang dikunjungi, saya perlu daftar node aktif. Diimplementasikan sebagai array mod_listdengan panjang mod_list_length.

Beberapa statistik runtime (pada mesin dengan RAM 16 GB, yang tampaknya penting untuk ukuran besar n, karena program mengalokasikan 5nbyte memori):

  • Input 99999999- 2 detik
  • Input 999999999- 27 detik (hasilnya 111111111222222222333333333444444444555555555666666666777777777888888889- mungkin hasil terbesar untuk bilangan bulat 32-bit)
  • Input 2147483647- 26 detik (hasilnya 4661316525084584315813)
  • Input 1999999998- 52 detik (mungkin jangka waktu terpanjang untuk integer 32-bit)
anatolyg
sumber
2
Saya memahami bahwa Anda setelah karunia, tapi bahkan jadi ini adalah kode-golf pertanyaan, dan aturan situs mengharuskan Anda untuk membuat beberapa upaya untuk golf kode Anda.
Peter Taylor
Program Anda memiliki 3546 byte.
aditsu
@aditsu Saya mengukur jumlah byte di Windows, yang menggunakan gaya CR / LF
anatolyg
4

C ++ 11, banyak byte, sangat cepat, wow (1,5 detik pada 1999999998, 0,2 detik pada 1… 10.000)

(Versi Python Golf di bawah.)

Kami mulai dengan konsep yang agak mirip dengan solusi aditsu, di mana kami secara induktif membangun koleksi sisa modular yang dapat dicapai dalam n langkah. Tetapi alih-alih menunggu sampai kita menemukan sisa 0, kita memeriksa dua sisa yang ditemukan a dan b sehingga a · 10 ^ n + b = 0. Pendekatan bertemu-di-tengah ini mengurangi kedalaman pohon pencarian, jadi itu adalah jauh lebih cepat pada input besar dan menggunakan memori jauh lebih sedikit.

Beberapa tolok ukur:

$ 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

Kode:

#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 byte (8,6 detik pada 1999999998 dengan 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
sumber
2
Saya memahami bahwa Anda setelah karunia, tapi bahkan jadi ini adalah kode-golf pertanyaan, dan aturan situs mengharuskan Anda untuk membuat beberapa upaya untuk golf kode Anda.
Peter Taylor
1
@ PeterTaylor, sangat baik, saya menambahkan versi golf dengan Python.
Anders Kaseorg
3

Mathematica 115 byte

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

Java 156 byte

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

Terima kasih banyak kepada aditsu :)

Joba
sumber
Anda tidak perlu spasi setelahnya [], ybisa longjuga, Anda lupa x*y+""trik dalam program ke-2, gunakan isEmptyalih-alih memeriksa panjangnya, gunakan ;alih-alih{}
aditsu
Pokoknya, selamat datang di kode golf :)
aditsu
Saya harus mengatakan, saya terkesan, tetapi membuat Anda longtidak akan membuat kode lebih pendek
Joba
Ya itu akan:long x=…,y;
aditsu
yharus dimulai dari 1, Anda dapat menginisialisasi dalam deklarasi, kelas Anda tidak perlu bersifat publik, dan Anda dapat pindah y++ke x*ybagian ( x*y++)
aditsu
2

Pyth - 12 11 byte

Gunakan filter dengan arg numerik untuk mendapatkan bilangan asli pertama yang memenuhi predikat, defaultnya adalah 1 yang kita inginkan. Setwise diff untuk memeriksa apakah hanya nol dan satu.

f!-j*QT10U2

Test Suite .

Maltysen
sumber
Konversikan ke string dan hapus "01. Menghemat satu char.
Jakube
2

R, 45 byte

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

Pemakaian:

> 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
sumber
2

Java, 198 193 181 byte

Terima kasih kepada @aditsu karena telah mengurangi 5 byte DAN meningkatkan rentang angka yang dapat diuji!

Perhatikan bahwa beberapa nilai loop negatif karena bagaimana Java mem-parsing bilangan bulat. Ini bisa dielakkan oleh BigInteger, tetapi bonus itu kurang berharga.

Saya tahu bahwa saya tidak akan menang, tetapi saya harap ini menginspirasi jawaban lain yang lebih pendek.

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

Tidak terbungkus:

kelas A {
   public static static utama (String [] a) {
      for (long i = 1;; i ++) {// infinite loop mulai dari 1
         coba {// jika ada kesalahan yang dilemparkan dengan mencoba menguraikan biner, mulai ulang sambil menambahkan 1 ke i
            long b = Long.parseLong (a [0]); // Untuk nanti - lebih pendek untuk menyatakan daripada menggunakan dua kali
            jika (b * i <0) putus; // Keluar dari program jika kita telah mengulang.
            Long.parseLong (b * i + "", 2); // Lipat gandakan dan lihat apakah bisa dilewati sebagai angka biner, jika tidak, buang kesalahan dan kembali ke atas loop
            System.out.println (b); // cetak itu
         } catch (Exception e) {} // tidak melakukan apa-apa saat catch
      }
   }
}
Addison Crump
sumber
2
Ini lucu yang Longlebih pendek dari Integer:)
anatolyg
3
Ironi yang paling harfiah ada.
Addison Crump
2

C, 107 101 byte ( 105 99 byte untuk 32-bit)

Ada kekurangan yang jelas dari jawaban dalam kode C pada golf. Memang, C bukan pilihan terbaik untuk menulis program sekecil mungkin, tetapi tidak seburuk itu:

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

Anda dapat melakukannya tanpa menyertakan #, tetapi semua definisi fungsi akan tersirat. Kelemahan utama adalah bahwa ini menyebabkan asumsi bahwa semua fungsi mengembalikan int. Ini adalah masalah pada mesin 64-bit untuk fungsi yang benar-benar mengembalikan pointer. Jika Anda menggunakan mesin 32-bit, 2 byte dapat dicukur dari solusi di atas:

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 yang lebih mudah dibaca:

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
sumber
2

C # waktu dekat 5 detik (1 hingga 10.000)

Seperti yang diminta, ini adalah program C # golf menjawab tantangan aslinya. Input sebagai argumen baris perintah, output ke konsol.

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

Kemudian, seperti untuk hadiah: hadiah harus pergi ke aditsu, karena saya pikir algoritme tidak dapat dikalahkan dalam hal kinerja. Tapi anatolyg jawaban sendiri juga luar biasa.

Berikut ini adalah implementasi cepat saya di C #. Saya kira di C ++ bisa lebih cepat (mungkin 2x). Dikompilasi dan diuji dengan Visual Studio 2010, .NET framework 4, 64 bit, mengarahkan output ke nul. Waktu: 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
sumber
Times 4.1s. Saya salah bicara di karunia. Dengan versi PyPy terbaru, versi aditsu yang lebih cepat kali sekitar 8-an, jadi ini dua kali lebih cepat.
Primo
Saya memahami bahwa Anda setelah karunia, tapi bahkan jadi ini adalah kode-golf pertanyaan, dan aturan situs mengharuskan Anda untuk membuat beberapa upaya untuk golf kode Anda.
Peter Taylor
Saya tidak mengejar hadiah, itu hanya contoh implementasi. Tapi Anda benar, saya akan menambahkan versi golf.
edc65
@PeterTaylor bisakah sekarang?
edc65
Ngomong-ngomong, mengapa Keys.Reverse? Apakah urutannya penting? Jika hanya untuk menghindari masalah konkurensi, ToListlebih pendek.
Peter Taylor
2

C dengan GMP (621 byte, cepat)

Saya sudah berusaha cepat dan pendek, tetapi disukai cepat. Implementasi ini menggunakan versi yang sedikit ditingkatkan dari percepatan teori angka yang saya sebutkan di komentar pada jawaban aditsu .

Simpan sebagai pseudobinary.cdan kompilasi dengangcc pseudobinary.c -lgmp -o pseudobinary . Perhatikan bahwa ini mengalokasikan begitu banyak memori untuk input besar sehingga Anda harus mengompilasinya untuk platform 64-bit.

#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 loop untuk timing (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 loop tidak disatukan

#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
sumber
2

C + GMP, 669

Ini sangat cepat untuk angka yang bertubuh kecil; mulai tersedak ketika hasilnya memiliki lebih dari 64 digit.

#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 yang dapat mencapai 10.000 (671 byte):

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

Berikut adalah beberapa perintah untuk menguji kode saya dan juga pesaing saya, dan hasilnya di laptop saya:

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
sumber
Sebuah jawaban yang layak mendapat hadiah. Saya menaruh perhatian khusus pada masalah ini (dan solusi awal Anda), karena ini adalah kasus khusus dari masalah jumlah subset , yang dikenal sebagai NP-complete (diberi daftar residu 10ⁱ mod n , temukan subset paling awal yang berjumlah n ).
Primo
@rimo Terima kasih :) Pendekatan saya di sini berbeda - Saya menggandakan jumlah digit pada setiap langkah daripada hanya menambahnya, dan saya juga memeriksa terlebih dahulu (sangat cepat) jika ada nomor baru yang akan menjadi solusi, sebelum benar-benar menghitung mereka. Dan saya yakin masih ada ruang untuk bermain golf.
aditsu
Menarik. Ketika saya mencoba menggandakan jumlah digit pada setiap langkah itu akhirnya menjadi lebih lambat. Mungkin pemeriksaan awal untuk solusi membuat perbedaan besar.
Peter Taylor
@PeterTaylor itu mungkin .. sepertinya Anda juga memanggil calloc dalam satu lingkaran, yang mungkin memperlambatnya. Ngomong-ngomong, saya ingin menambahkan versi kode saya yang tidak disatukan ketika saya menemukan waktu, dan saya juga punya ide bagaimana membuatnya lebih cepat untuk angka yang lebih besar / lebih jahat.
aditsu
2

T-SQL, 164 156 155 154 159 byte

(-1 byte. Terima kasih Jonathan!)

(-1 lebih karena mengapa saya memiliki spasi di belakang garis? SMH)

(+5 menyadari golf saya memecahkan banyak hal)

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

Saya tidak tahu mengapa saya terus kembali ke pertanyaan-pertanyaan ini di mana saya seharusnya mengonversi ke Biner ... T-SQL tidak tahu bagaimana melakukannya dengan benar.

Bagaimanapun, ini adalah SQLFiddle .

Tidak golf:

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

Sebagian besar hal ini diperlukan untuk menulis fungsi dalam T-SQL, sejauh yang saya ketahui.

    declare @bin nvarchar(max) = ''

Buat string kosong yang akan kita simpan sebagai nomor biner kita.

    declare @id2 int = @id

Simpan nilai input untuk digunakan di akhir. Sepertinya harus ada cara untuk menggunakan input asli bahkan jika kita mengubah nilainya, tetapi saya tidak dapat menemukannya.

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

Jadi kami mengambil input asli kami, MOD dengan 2 untuk menemukan sisanya, dan itu akan menjadi digit terkecil kami berikutnya. Misalnya, 5% 2 = 1

        SET @id = @id/2

Lalu kami mengambil nomor kami, dan membaginya menjadi dua. Karena ini adalahint tipe, ia membulatkannya ke bilangan bulat terdekat, jadi 5/2 = 2. END Kami kemudian mengulangi ini sampai nilainya 0. Jadi kita berakhir dengan 5% 2 = 1 5/2 = 2 2 % 2 = 0 2/2 = 1 1% 2 = 1 1/2 = 0 yang memberi kita nilai string biner kami dari 101.

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

Kami mengambil string biner kami dan mengubahnya kembali menjadi yang lain int.

    return @binNum/@id2

Kami mengembalikan string biner kami intdibagi dengan nilai asli kami, sesuai dengan asal pertanyaan.

END
phroureo
sumber
Apakah ruang dalam @>0 SELECTtidak bisa dihilangkan?
Jonathan Frech
Tangkapan bagus! Saya tidak pernah ingat ruang apa yang bisa
dihilangkan
Sebagian besar waktu Anda dapat menghilangkan spasi di antara literal dan variabel / kata kunci, karena mereka tidak dapat memulai dengan angka.
Jonathan Frech
1

Ruby, 46 byte

Saya harus benar-benar menghilangkan loop sementara dengan loop alternatif.

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

Sunting: Terima kasih @manatwork untuk mencukur 1 byte!

Sunting2: Terima kasih @histocraft untuk 9 byte yang gila!

Sunting: Terima kasih @manatwork lagi untuk mencukur 7 byte!

Peter Lenkefi
sumber
z!=z[/[01]+/]lebih pendek. z[/[^01]/]bahkan lebih pendek.
manatwork
@manatwork Terima kasih! 1 byte lebih sedikit!
Peter Lenkefi
2
Single-line sementara loop cenderung menjadi yang terpendek:z="#{n.to_i*k+=1}"while z[/[^01]/]
histokrat
@ histokrat Itu 9 byte! Dan saya bahkan tidak tahu bahwa ruby ​​mampu melakukan ini. Terima kasih!
Peter Lenkefi
Menarik bahwa Anda tidak mengubah tes untuk set karakter dinegasi tidak setelah disarankan kedua kalinya. Alasan apapun?
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 yang mudah dibaca

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

gawk4 brute force, 28 + 2 = 30 byte

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

Perlu dipanggil dengan -M opsi untuk menggunakan nomor besar. Tentu saja ini sangat lambat, menggunakan angka besar memperlambatnya bahkan lebih, tetapi secara teoritis inputnya tidak terbatas, dan penggunaan RAM dapat diabaikan.

Contoh penggunaan (jika Anda punya waktu untuk dihabiskan ;))

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

gawk4 dioptimalkan, 69 + 2 = 71 byte

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

Nah, ini akhirnya menjadi klon dari jawaban aditsu. Setelah melihat pertanyaan ini saya masih mencari cara untuk membuat kode bagian subset-sum, ketika saya tidak bisa menolak melihat jawaban lain di sini.

Dalam elemen awk array memiliki perilaku (aneh?) Bahwa jika Anda membandingkan elemen yang tidak ada dengan sesuatu itu entah bagaimana diinisialisasi sebagai kosong sebelum dibandingkan (saya akui bahwa saya tidak begitu yakin tentang apa yang terjadi di sana). Jadi setelah memeriksa !a[0]yang for(i in a)lingkaran dimulai bahkan tanpa menginisialisasi a[$0]ke0 sebagai aditsu lakukan.

Tentu saja -M opsi harus digunakan untuk ini juga.

Meskipun agak cepat masih lebih lambat dari Python. Untuk 79992ini membutuhkan sekitar 14 detik pada Core2Duo 2GHz saya. Dan saya tidak akan mengatakan itu bekerja untuk input hingga 2 ^ 31, karena dalam kasus terburuk itu harus membangun array angka besar (gawk4 menggunakan GMP untuk ini), yang memiliki ukuran nomor input. Sebagai 'bonus' array besar sangat lambat di awk ...

Cabbie407
sumber
1

Dyalog APL , 25

Ini mendefinisikan program yang tepat "P" (bukan hanya fungsi yang tidak disebutkan namanya):

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

2∘mulai dengan 2 sebagai argumen kiri
0::jika ada kesalahan ...
⍵∇⍨1+⍺panggil dirinya dengan argumen
⍺×⍵kiri yang bertambah, gandakan argumen kiri dan kanan
menjadi string
⍎¨ buat setiap karakter menjadi
~upaya angka BUKAN logis (jika gagal, pergi ke penanganan kesalahan di atas, lain ...)
⍺⊣kembalikan argumen kiri saat ini.

      P 2
50
      P 21
481
      P¨⍳8    ⍝ 1 through 8
10 5 37 25 2 185 143 125
Adm
sumber