Tìm bội số của một số đã cho có biểu diễn thập phân trông giống như nhị phân


34

Tôi đã bắt gặp một câu hỏi trên trang web Code Review có vẻ thú vị. Tôi nghĩ OP đang làm sai, nhưng không thể chắc chắn ... Vì vậy, hãy giải quyết nó cho anh ấy! (viết chương trình, không phải chức năng / thủ tục)

Đầu vào (stdin hoặc tương tự):

Một số nguyên xtrong ký hiệu thập phân. Nó lớn hơn 1 và nhỏ hơn 2 ^ 31.

Đầu ra (thiết bị xuất chuẩn hoặc tương tự):

Một số nguyên ytrong ký hiệu thập phân. Sản phẩm x * ytrong biểu diễn thập phân phải chỉ chứa các chữ số 0 và 1. Nó phải là số tối thiểu như vậy lớn hơn 0.

Lưu ý: đầu ra không bị giới hạn - nếu mức tối thiểu ykhoảng 10 ^ 100, chương trình của bạn phải xuất tất cả 100 chữ số của nó (Tôi không biết có giới hạn hợp lý nào không, như 2 ^ 64, trên y- không giải quyết được ).

Chương trình của bạn sẽ kết thúc trong một thời gian hợp lý (1 giây? 1 giờ? - đại loại như thế) cho tất cả xtrong phạm vi.

Tiền thưởng:

Nếu chương trình của bạn không có giới hạn về kích thước của đầu vào (ngoại trừ RAM) và có độ phức tạp đa thức, hãy nhân số byte của chương trình của bạn 0.8và làm tròn xuống.


Ví dụ: Đầu vào 2; đầu ra 5, vì 2 * 5 = 10

Ví dụ: Đầu vào 21; đầu ra 481, vì 21 * 481 = 10101


Tuyên bố miễn trừ trách nhiệm: Tôi không chịu trách nhiệm cho câu hỏi trên trang web Xem lại mã. Trong trường hợp có bất kỳ sự khác biệt nào, chỉ nên xem mô tả ở trên là thông số kỹ thuật phù hợp.

OEIS A079339


6
Nó phải luôn luôn có thể giải được. Rõ ràng phải tồn tại ít nhất một q sao cho có vô số n sao cho 10 ^ n mod x = q. Lấy x các giá trị như vậy của n và cộng các lũy thừa tương ứng 10 ^ n.
frageum

1
Bội số của 9 dường như tạo ra kết quả cao bất thường.
SuperJedi224

1
Vấn đề liên quan đến Dự án Euler , đối với bất kỳ ai khác nghĩ rằng câu hỏi này trông quen thuộc
Sp3000

1
Theo độ phức tạp đa thức, bạn có nghĩa là đa thức trong số chữ số của đầu vào, hay đa thức trong giá trị của đầu vào?
Reto Koradi

3
@anatolyg của tôi không phải là vũ phu
aditsu

Câu trả lời:


8

Bình thường, 9 byte

f!-`*TQ10

Trình diễn

Đối với mỗi bội số, chuyển đổi thành một chuỗi, trừ đi các chữ số trong 10(sử dụng int int của Pyth để tạo chuỗi trong trường hợp này) và sau đó phủ nhận một cách hợp lý kết quả, chỉ chấm dứt tìm kiếm khi tìm thấy bội số chính xác.

Giải pháp thưởng, 10 byte:

f.xi`*TQ2Z

Giải pháp này thực sự kiểm tra xem đại diện chuỗi của số có thể được coi là số nhị phân ( i ... 2) và chấm dứt khi không xảy ra lỗi trong lần thử này.


18

Python 2, giải pháp hiệu quả, 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

Cảm ơn Sp3000 cho một số mẹo chơi golf.

Tôi thách thức mọi người khác đăng bài (bằng câu trả lời của riêng họ) mất bao lâu để có kết quả cho đầu vào 72hoặc 99:) Nếu những thứ đó thực sự nhanh, hãy thử một cái gì đó như 79992tiếp theo (vẫn <1 giây ở đây).

Giải trình:

Tôi nghĩ rằng điều này là không cần thiết (vì mã này khá dễ đọc), nhưng tôi đã nhận được một yêu cầu, vì vậy nó ở đây:

Ý tưởng đầu tiên là một số có vẻ nhị phân là tổng của 1 hoặc nhiều lũy thừa khác nhau của 10. Do đó, chúng ta có thể thử thêm các lũy thừa khác nhau của 10 theo các cách khác nhau cho đến khi chúng ta nhận được 0 còn lại.

Nếu chúng ta làm điều đó một cách ngây thơ, thì cũng giống như tạo ra tất cả các số trông nhị phân và kiểm tra chúng. Nhưng rất nhiều phần còn lại sẽ giống nhau. Một cách tốt hơn là chỉ ghi lại số nhỏ nhất đưa ra một số còn lại nhất định và liên tiếp thêm các lũy thừa 10 vào số chúng tôi đã ghi. Đó là những gì chương trình làm.

dlà một từ điển / bản đồ trong đó các khóa là phần còn lại và các giá trị là các số trông nhị phân với phần còn lại. Trường hợp ban đầu n:0là một trường hợp đặc biệt: đáng lẽ 0:0chúng ta phải bắt đầu thêm sức mạnh cho nó, nhưng thuật toán dừng lại khi tìm khóa 0, vì vậy tôi đã sử dụng nthay thế, được đảm bảo có tác dụng tương tự và không can thiệp vào các giá trị khác.

Sau đó, chúng tôi bắt đầu thêm quyền hạn 10 (được lưu trữ k) vào tất cả các số hiện có và ghi lại phần còn lại. Chúng tôi thêm kvào phần còn lại: (x+k)%nvà vào số : d[x]+k, và chỉ ghi lại nếu đó là phần còn lại mới : d.setdefault(…), sau đó chuyển sang nguồn tiếp theo: k*=10và lặp lại cho đến khi chúng tôi nhận được khóa 0:while min(d)

Cuối cùng, d[0]đưa ra số tìm kiếm nhị phân có 0 mod còn lại n, vì vậy chúng tôi chia nó ncho để có được giải pháp.

Lưu ý: chương trình có thể được thực hiện hiệu quả hơn bằng cách tránh số lượng lớn (ghi số mũ thay vì lũy thừa 10 và tính toán phần còn lại của các quyền lực từ các giá trị trước đó), nhưng đó là mã golf, vì vậy ...

Trong thực tế, ở đây, tôi đã viết một phiên bản nhanh hơn:

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

1
Câu trả lời của tôi cũng không nhận được. xD "Dangit, Java, nguyền rủa sự lựa chọn Integer.MAX_VALUE của bạn khi sử dụng BigInteger theo mặc định!" - Mỗi lập trình viên Java từng có
Addison Crump

@VTCAKAVSMoACE tại sao bạn không sử dụng Long?
aditsu

Hừm. Đó là một byte thêm, nhưng ... đáng giá. Cảm ơn!
Addison Crump

Hay không. Điều đó thực sự làm giảm nghiêm trọng nó. Cảm ơn!
Addison Crump

1
Thời gian để giải 99: aditsu: 0,001 giây; xnor: 5+ giờ và nó vẫn chưa hoàn thành.
dùng193661

13

Python 2, 47 byte

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

Theo dõi số đầu vào nvà bội số hiện tại a. Khi atrông giống như nhị phân, xuất tỷ lệ a/n. Để kiểm tra xem một số được tạo thành từ 01, chúng ta so sánh char tối đa trong biểu diễn chuỗi của nó với '1'.

Sử dụng str(a)thay vì `a`để tránh kết thúc dài L. Thật không may, 'L'là lớn hơn '1'.


12

Perl, 27 byte

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

Đếm shebang là một, đầu vào được lấy từ stdin.

Sử dụng mẫu

$ 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}{

Một cải tiến hai byte bởi @skmrx .

Thay vì kiểm tra dựa trên biểu thức chính quy, điều này thay vào đó cố gắng đánh giá sản phẩm dưới dạng chữ nhị phân. Khi thất bại, nó chuyển sang tiếp theo. Thông thường, octhàm sẽ được sử dụng cho mục đích này, nhưng nó âm thầm cắt các chữ số không hợp lệ, không hữu ích trong thử thách này.


Perl, 40 byte

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

Một giải pháp hiệu quả hơn nhiều. Chúng tôi lặp lại các biểu diễn nhị phân, diễn giải chúng là cơ sở 10, và sau đó kiểm tra tính phân chia. Thời gian chạy cho tất cả các giá trị dưới 100 là không đáng kể.

Sử dụng mẫu

$ echo 72|perl dec-bin.pl
1543209875

$ echo 99|perl dec-bin.pl
1122334455667789

2
Nice :) Tôi đã học được một vài điều mới từ bài viết của bạn ngày hôm nay! Trong khi đọc qua mã của bạn, tôi đã tìm ra cách để loại bỏ một vài byte từ mã đầu tiên:eval"0b".$_*++$\||redo}{
svsd

Nhưng tôi đoán chúng tôi sẽ cần bao gồm use bigintđể hỗ trợ số lượng lớn mà OP bắt buộc phải được hỗ trợ :(
svsd

1
@skmrn Thật tuyệt vời. Tôi đã thử oct'0b'.++$\*$_, nhưng nó âm thầm cắt các chữ số không hợp lệ. Tôi không nghĩ sẽ sử dụng evalthay thế.
primo

11

Javascript, 43 byte

Điều này đã kết thúc ngắn hơn tôi nghĩ. Về cơ bản nó increments ylên 1 cho đến khi y * (input number) = (binary-looking number). Rõ ràng là không hiệu quả.

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


Javascript (giải pháp hiệu quả hơn), 53 byte

Điều này tăng ytrong nhị phân cho đến khi y / (input number) = (number without a remainder). Sau đó, nó xuất ra (number without a remainder).

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


Javascript (giải pháp thậm chí hiệu quả hơn), 76 byte

Điều này kết hợp cả hai phương pháp trước đây được mô tả ở trên. Nó kiểm tra mức tăng ycho đến khi y * (input number) = (binary-looking number)(có nghĩa là đầu ra là y) HOẶC y / (input number) = (number without a remainder)(có nghĩa là đầu ra là (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)


Nó sẽ cung cấp 1 khi có thể (ví dụ đầu vào: 1)
edc65

@ edc65 Đã sửa lỗi - không thay đổi số byte!
Mama Fun Roll

Điều này làm sập Safari 9.0. Jussayin '. :)
Addison Crump

1
Nhưng nó giới hạn ở số lượng nhỏ trong đầu ra. Số Javascript có độ chính xác 17 chữ số, OP đang yêu cầu một cái gì đó lớn hơn (và nó có thể được thực hiện bằng cách sử dụng số học mô-đun)
edc65

Protip: Đừng thử nhập 72. Firefox 41 đóng băng trong 15 phút và sau đó gặp sự cố. Tôi phát hiện ra điều này một cách khó khăn.
Sản xuất ETH

9

Haskell, 72 70 64 60 58 byte

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

Chỉnh sửa: @Jan Dvorak đã giúp tôi tiết kiệm 4 byte.

Chỉnh sửa: @BlackCap đã lưu 2 byte bằng cách chuyển sang doký hiệu. Cảm ơn!


main=print.f=<<readLn
John Dvorak

Bạn có thể lưu một byte bằng cách nội tuyến f:main=readLn>>= \x->print$[y|y<-[1..],all(<'2')$show$x*y]!!0
BlackCap

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

@BlackCap: Tốt đẹp! Cảm ơn rất nhiều!
nimi

7

Python 2, 67 65 63 60 byte

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

Cảm ơn Status cho 2 byte và Shebang cho 5 byte!


1
Tôi nghĩ bạn phải khởi tạob=1
anatolyg

2
Bạn có thể cạo 2 byte bằng cách thực hiệnany(c in`a*b`for c in'23456789')
Trạng thái

1
Tôi không chắc chắn về điều này nhưng sẽ not c in`a*b`for c in'10'làm việc?
cole

2
Bạn có thể lưu 6 byte bằng cách thay đổi điều kiện while của bạn thành set('a*b')&set('23456789').
Kade

2
`tạo ra một thời gian Ldài và 'L'>'1'.
dùng193661

6

JavaScript (ES6) 222 250

Sử dụng toán chính xác tùy ý (hoạt động trên chuỗi các chữ số thập phân)

Điều này có thể được đánh gôn nhiều hơn một chút (được thực hiện), nhưng tôi thích thực tế rằng nó không bị giới hạn ở các số tiêu chuẩn JS (17 chữ số thập phân chính xác) và nó rất nhanh.

Kiểm tra chạy đoạn mã dưới đây trong trình duyệt tuân thủ EcmaScript 6. Thời gian có thể chấp nhận lên tới 9998 - đừng thử 9999 và kiên nhẫn với 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>

Dễ đọc hơn

Đây là phiên bản đầu tiên, với mô đun và phân chia dài như các chức năng tách biệt.

// 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]
}

Tôi đã làm cho nó hoạt động trong Firefox, nhưng dường như nó không xử lý số lượng lớn hơn, ví dụ 999
aditsu

Tôi có một phiên bản mới có thể xử lý 999 trong 36 giây, nhưng không có hy vọng đạt được 9999 với thời gian chờ javascript (mỗi '9' được thêm vào cần 2 ^ 9 (~ 500) lần thời gian để kết thúc)
edc65

@aditsu đó là cách tốt nhất tôi có thể làm trong JavaScript (nhưng trong C # thì hoàn toàn giống nhau). Luôn luôn chờ đợi một lời giải thích về thuật toán đáng kinh ngạc của bạn
edc65

Tôi nói thêm một lời giải thích tại
aditsu



4

PHP, 50 bytes

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

Some test cases

1 > 1
2 > 5
12 > 925
21 > 481

1
Was gonna make something like this, this is even a tad shorter than I had in mind
Martijn

4

CJam, 19 17 16 bytes

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

Try it online

Brute force solution, trying values sequentially until one meeting the condition is found.

The latest version saves 2 bytes thanks to using As instead of "01" to build a string containing 0 and 1, as suggested by @aditsu. The full proposed solution in the comment saves another byte, but it looks fairly different from mine, so I didn't want to post it under my name.

And 1 more byte saved by @Dennis.

Explanation:

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.

3
16:li0{1$+_sAs-}g\/
aditsu

Cảm ơn, @aditsu. Tôi thực sự không muốn sao chép giải pháp đầy đủ của bạn dưới tên của tôi. Tôi đã thực hiện Asđể xây dựng chuỗi, vì đó là một thay đổi rất cục bộ, mà nhìn chung (điều này luôn dễ dàng hơn nhiều ...) tôi nên nghĩ đến.
Reto Koradi

1
@RetoKoradi 16 byte, ít sửa đổi hơn: li:V!{)_V*sAs-}gNgoài ra, 0{)_easi*sAs-}g(15 byte) hoạt động với trình thông dịch Java và các đối số dòng lệnh.
Dennis

4

Python 3 2, 101 76 byte

-25 byte nhờ @aditsu

gần như hiệu quả như giải pháp của @ 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

Thay vì cố gắng lặp qua các bội số theo thứ tự tăng dần, tôi đang cố gắng lặp qua các sản phẩm mà tôi đang tạo ở dạng 'nhị phân'.


Không tệ :) Còn 9999 thì sao?
aditsu

2
Một số mẹo chơi gôn: sử dụng python 2 ( n=input()), while b%n:(khởi tạo bthành 1), không thụt lề
aditsu

@aditsu Cảm ơn! 9999 hmmm, có vẻ như sẽ mất vài ngày, quay lại bảng vẽ -_-
Rnet

1
bin(m)[2:]nên ngắn hơn chuỗi định dạng. Giao đôi b=m=1nên tiết kiệm một vài là tốt.
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);}}

Công dụng BigInteger và như vậy có (cho tất cả các mục đích và mục đích hợp lý) kích thước đầu vào không giới hạn. Không chắc chắn về sự phức tạp mặc dù, điều đó phụ thuộc vào tốc độ tăng trưởng của chức năng của chúng tôi ở đây.

Cảm ơn geobits và ypnypn vì đã tiết kiệm được một số byte.


Xin chào, làm thế nào bạn sẽ gọi điều này trong phương pháp chính của bạn xin vui lòng? Thử nhưng không thành công
Yassin Hajaj

Bạn sẽ phải thêm công cụ staticsửa đổi cho phương thức.
SuperJedi224

1
Câu hỏi nói rằng giải pháp nên là một chương trình hoàn chỉnh, không chỉ là một chức năng.
raznagul

Bạn có thể cắt 15 với b.ONE!(b.multiply(c)+"")(thay vì toString()).
Geobits

@raznagul: Đã sửa.
SuperJedi224

4

C, 3675 byte

Quá lâu cho 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);
    }
}

Chạy không có tham số dòng lệnh - nó nhận được ntừ stdinvà đưa ra kết quả stdout. Chạy với một tên tệp - nó ghi kết quả n = 1...10000vào tệp đó và đo thời gian.

Hiệu suất trong 1 ... 10000: 140 ms

Mã này sử dụng thuật toán được đề xuất bởi aditsu , được triển khai trong C cho tốc độ. Tôi đã không nỗ lực để chơi nó, vì vậy mã sẽ dễ đọc hơn.

Tôi đã triển khai nó đầu tiên trong C ++ bằng cách sử dụng std::mapđể ghi lại kết quả tìm kiếm và nó khá chậm. Tuy nhiên, các khóa của các mapsố nguyên liên tiếp (tôi gọi chúng modlà s, vì chúng đại diện cho số modulo n), vì vậy việc sử dụng một mảng là điều tự nhiên - vì vậy tôi viết lại nó trong C.

Một tối ưu hóa bổ sung liên quan đến các giá trị của ánh xạ - để tránh lưu trữ một số nguyên lớn cho mỗi mod, tôi chỉ lưu trữ sức mạnh lớn nhất trong số 10 ở đó - đó là thông tin vừa đủ để đi đến trước đó mod. Vì vậy, mảng thực sự là một cây / đồ thị tìm kiếm. Khi tìm kiếm đếnmod = 0 , truy tìm các nút của cây trở lại gốc sẽ cho các quyền hạn 10 theo thứ tự giảm dần.

Vì tìm kiếm thường dừng khá nhanh, chỉ với một phần nhỏ các nút được truy cập, tôi cần một danh sách các nút hoạt động. Nó được thực hiện như một mảng mod_listvới chiều dàimod_list_length .

Một số thống kê thời gian chạy (trên máy có RAM 16 GB, có vẻ rất quan trọng nvì chương trình phân bổ 5nbyte bộ nhớ):

  • Đầu vào 99999999- 2 giây
  • Đầu vào 999999999- 27 giây (kết quả là111111111222222222333333333444444444555555555666666666777777777888888889 - có thể là kết quả lớn nhất có thể có cho số nguyên 32 bit)
  • Đầu vào 2147483647- 26 giây (kết quả là 4661316525084584315813)
  • Đầu vào 1999999998- 52 giây (có lẽ là thời gian chạy lâu nhất có thể cho số nguyên 32 bit)

2
Tôi hiểu rằng bạn đang theo đuổi tiền thưởng, nhưng ngay cả vậy đây là một câu hỏi về môn đánh gôn và các quy tắc của trang web yêu cầu bạn phải thực hiện một số nỗ lực để đánh golf mã của mình.
Peter Taylor

Chương trình của bạn có 3546 byte.
aditsu

@aditsu Tôi đã đo số byte trong Windows, sử dụng kiểu CR / LF
anatolyg

4

C ++ 11, nhiều byte, rất nhanh, wow (1,5 giây trên 1999999998, 0,2 s trên 1 10000 10000)

(Phiên bản Python được đánh gôn bên dưới.)

Chúng tôi bắt đầu với một khái niệm hơi giống với giải pháp của aditsu, nơi chúng tôi tự xây dựng một bộ sưu tập các phần còn lại theo mô-đun có thể tiếp cận trong n bước. Nhưng thay vì đợi cho đến khi chúng tôi tìm thấy phần còn lại 0, chúng tôi kiểm tra hai phần còn lại tìm thấy a và b sao cho a · 10 ^ n + b = 0. Cách tiếp cận giữa chừng này giảm một nửa độ sâu của cây tìm kiếm, vì vậy nó nhanh hơn nhiều về đầu vào lớn và sử dụng ít bộ nhớ hơn.

Một số điểm chuẩn:

$ 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

Mã số:

#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 giây trên 1999999998 với 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()

2
Tôi hiểu rằng bạn đang theo đuổi tiền thưởng, nhưng ngay cả vậy đây là một câu hỏi về môn đánh gôn và các quy tắc của trang web yêu cầu bạn phải thực hiện một số nỗ lực để đánh golf mã của mình.
Peter Taylor

1
@PeterTaylor, rất tốt, tôi đã thêm một phiên bản chơi gôn trong Python.
Anders Kaseorg

3

Toán học 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]]

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

Cảm ơn rất nhiều đến aditsu :)


Bạn không cần một khoảng trống sau [], ycũng có thể long, bạn đã quên x*y+""mẹo trong chương trình thứ 2, sử dụng isEmptythay vì kiểm tra độ dài, sử dụng ;thay vì{}
aditsu

Dù sao, chào mừng bạn đến với mã golf :)
aditsu

Tôi phải nói rằng, tôi rất ấn tượng, nhưng làm cho bạn longsẽ không làm cho mã ngắn hơn
Joba

Có, nó sẽ:long x=…,y;
aditsu

yphải bắt đầu từ 1, bạn có thể khởi tạo nó trong phần khai báo, lớp của bạn không cần phải công khai và bạn có thể chuyển y++sang x*yphần ( x*y++)
aditsu

2

Pyth - 12 11 byte

Sử dụng bộ lọc với đối số số để có được số tự nhiên đầu tiên đáp ứng vị ngữ, mặc định là 1, đó là những gì chúng ta muốn. Setwise diff để kiểm tra nếu chỉ có số không và số không.

f!-j*QT10U2

Phòng thử nghiệm .


Chuyển đổi thành chuỗi và loại bỏ "01. Lưu một char.
Jakube

2

R, 45 byte

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

Sử dụng:

> 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

2

Java, 198 193 181 byte

Cảm ơn @aditsu đã loại bỏ 5 byte VÀ tăng phạm vi số có thể kiểm tra!

Lưu ý rằng một số giá trị lặp một cách tiêu cực do cách Java phân tích các số nguyên. Điều này có thể bị BigInteger phá vỡ, nhưng phần thưởng đơn giản là ít giá trị hơn.

Tôi biết rằng tôi sẽ không giành chiến thắng, nhưng tôi hy vọng điều này sẽ truyền cảm hứng cho những câu trả lời khác, ngắn hơn.

class A {public static void main (String [] a) {for (long i = 1 ;; i ++) {thử {long b = Long.parseLong (a [0]); if (b * i <0) break; Long.parseLong (b * i + "", 2); System.out.println (i);} bắt (Ngoại lệ e) {}}}}

Ủng hộ:

lớp A {
   công tĩnh void chính (Chuỗi [] a) {
      for (long i = 1 ;; i ++) {// vòng lặp vô hạn bắt đầu từ 1
         thử {// nếu một lỗi được đưa ra bằng cách thử phân tích thành nhị phân, khởi động lại trong khi thêm 1 vào i
            dài b = Long.parseLong (a [0]); // Để sau này - khai báo ngắn hơn sử dụng hai lần
            nếu (b * i <0) phá vỡ; // Thoát ra khỏi chương trình nếu chúng ta đã lặp.
            Long.parseLong (b * i + "", 2); // Nhân ra và xem nếu nó có thể qua được dưới dạng số nhị phân, nếu không, hãy ném lỗi và quay lại đầu vòng lặp
            System.out.println (b); // in nó ra
         } Catch (Exception e) {} // không làm gì khi bắt
      }
   }
}

2
Thật buồn cười Longlà ngắn hơn Integer:)
anatolyg

3
Nhất đen trớ trêu có.
Addison Crump

2

C, 107 101 byte ( 105 99 byte cho 32 bit)

Có một câu trả lời thiếu rõ ràng trong C về mã golf. Thật vậy, C không phải là lựa chọn tốt nhất để viết chương trình nhỏ nhất có thể, nhưng nó không tệ:

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

Bạn có thể thực hiện mà không có #includes, nhưng sau đó tất cả các định nghĩa hàm sẽ được ẩn. Hạn chế chính là điều này gây ra giả định rằng tất cả các hàm trả về ints. Đây là một vấn đề trên các máy 64 bit cho các hàm thực sự trả về một con trỏ. Nếu bạn đang sử dụng máy 32 bit, 2 byte có thể được loại bỏ giải pháp trên:

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

Phiên bản dễ đọc hơn:

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

2

Thời gian C # gần 5 giây (1 đến 10000)

Theo yêu cầu, đây là một chương trình C # đánh gôn trả lời thử thách ban đầu. Nhập dưới dạng đối số dòng lệnh, đầu ra cho bàn điều khiển.

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

Sau đó, đối với tiền thưởng: tiền thưởng nên đến aditsu, vì tôi nghĩ thuật toán của anh ta có thể bị đánh bại về mặt nước hoa. Nhưng anatolyg tự trả lời là tuyệt vời quá.

Đây là triển khai nhanh của tôi trong C #. Tôi cho rằng trong C ++ nó có thể nhanh hơn (có thể gấp 2 lần). Được biên dịch và thử nghiệm với Visual Studio 2010, .NET framework 4, 64 bit, chuyển hướng đầu ra sang nul. Thời gian: 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);
   }
}

Thời gian 4.1s. Tôi sai chính tả trong tiền thưởng. Với phiên bản mới nhất của PyPy, phiên bản nhanh hơn của aditsu khoảng 8 giây, do đó, tốc độ này nhanh gấp đôi.
primo

Tôi hiểu rằng bạn đang theo đuổi tiền thưởng, nhưng ngay cả vậy đây là một câu hỏi về môn đánh gôn và các quy tắc của trang web yêu cầu bạn phải thực hiện một số nỗ lực để đánh golf mã của mình.
Peter Taylor

Tôi không theo sau tiền thưởng, đó chỉ là một ví dụ về việc thực hiện. Nhưng bạn nói đúng, tôi sẽ thêm một phiên bản chơi gôn.
edc65

@PeterTaylor nó có thể đi bây giờ?
edc65

Nhân tiện, tại sao Keys.Reverse? Là thứ tự quan trọng? Nếu nó chỉ để tránh các vấn đề tương tranh, ToListthì ngắn hơn.
Peter Taylor

2

C với GMP (621 byte, nhanh)

Tôi đã cố gắng nhanh và ngắn, nhưng được yêu thích nhanh. Việc triển khai này sử dụng một phiên bản cải tiến một chút về tốc độ lý thuyết số mà tôi đã đề cập trong một nhận xét về câu trả lời của aditsu .

Lưu dưới dạng pseudobinary.cvà biên dịch với gcc pseudobinary.c -lgmp -o pseudobinary. Lưu ý rằng điều này phân bổ rất nhiều bộ nhớ cho các đầu vào lớn mà bạn sẽ cần phải biên dịch nó cho nền tảng 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;}

Phiên bản vòng lặp cho thời gian (751 byte)

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

Phiên bản vòng lặp

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

2

C + GMP, 669

Điều này thực sự nhanh chóng đối với số lượng nhỏ; nó bắt đầu nghẹt thở khi kết quả có hơn 64 chữ số.

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

Phiên bản vòng lặp tới 10000 (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));}}

Dưới đây là một số lệnh để kiểm tra mã của tôi cũng như của đối thủ cạnh tranh và kết quả trên máy tính xách tay của tôi:

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

Một câu trả lời xứng đáng của một tiền thưởng. Tôi đặc biệt quan tâm đến vấn đề này (và giải pháp ban đầu của bạn), vì đây là trường hợp đặc biệt của vấn đề tổng tập hợp con , được biết là NP-đầy đủ (đưa ra danh sách các dư lượng của 10ⁱ mod n , tìm tập hợp con sớm nhất mà tính tổng n ).
primo

@primo Cảm ơn bạn :) Cách tiếp cận của tôi ở đây khác - Tôi nhân đôi số chữ số ở mỗi bước thay vì chỉ tăng nó và tôi cũng kiểm tra trước (rất nhanh) nếu bất kỳ số nào mới là giải pháp, trước khi thực sự tính toán họ Và tôi chắc chắn rằng vẫn còn chỗ để chơi gôn.
aditsu

Hấp dẫn. Khi tôi cố gắng nhân đôi số chữ số ở mỗi bước thì cuối cùng nó sẽ chậm hơn. Có thể việc kiểm tra trước các giải pháp tạo ra sự khác biệt lớn.
Peter Taylor

@PeterTaylor điều đó là có thể .. có vẻ như bạn cũng đang gọi calloc trong một vòng lặp, điều này có thể làm chậm nó. Dù sao, tôi muốn thêm một phiên bản mã không được mã hóa khi tôi tìm thấy một thời gian và tôi cũng có một ý tưởng làm thế nào để làm cho nó nhanh hơn cho các số lớn hơn / nhanh hơn.
aditsu

2

T-SQL, 164 156 155 154 159 byte

(-1 byte. Cảm ơn Jonathan!)

(-1 thêm vì tại sao tôi có dấu cách trên dòng? SMH)

(+5 nhận ra việc chơi golf của tôi đã phá vỡ mọi thứ)

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

Tôi không biết tại sao tôi tiếp tục quay lại những câu hỏi này khi tôi phải chuyển đổi sang Binary ... T-SQL không biết làm thế nào cho đúng.

Trong mọi trường hợp, đây là SQLFiddle .

Chưa chơi gôn:

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

Hầu hết những thứ này là bắt buộc để viết một hàm trong T-SQL, theo như tôi biết.

    declare @bin nvarchar(max) = ''

Tạo một chuỗi trống mà chúng tôi sẽ lưu trữ dưới dạng số nhị phân của chúng tôi.

    declare @id2 int = @id

Lưu giá trị đầu vào để sử dụng ở cuối. Có vẻ như nên có một cách để sử dụng đầu vào ban đầu ngay cả khi chúng tôi thay đổi giá trị, nhưng tôi không thể tìm thấy.

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

Vì vậy, chúng tôi lấy đầu vào ban đầu của mình, MOD với 2 để tìm phần còn lại và đó sẽ là chữ số nhỏ nhất tiếp theo của chúng tôi. Ví dụ: 5% 2 = 1

        SET @id = @id/2

Sau đó, chúng tôi lấy số của chúng tôi, và chia nó một nửa. Bởi vì nó là một intloại, nó làm tròn nó xuống thành số nguyên gần nhất, vì vậy 5/2 = 2. KẾT THÚC Chúng tôi sau đó lặp lại giá trị này cho đến khi giá trị bằng 0. Vì vậy, chúng tôi kết thúc với 5% 2 = 1 5/2 = 2 2 % 2 = 0 2/2 = 1 1% 2 = 1 1/2 = 0 mang lại cho chúng ta giá trị chuỗi nhị phân là 101.

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

Chúng tôi lấy chuỗi nhị phân của chúng tôi và chuyển đổi nó trở lại một intlần nữa.

    return @binNum/@id2

Chúng tôi trả về chuỗi nhị phân intchia cho giá trị ban đầu của chúng tôi, theo nguồn gốc của câu hỏi.

END

Là không gian trong @>0 SELECTkhông thể bỏ qua?
Jonathan Frech

Bắt tốt đẹp! Tôi không bao giờ có thể nhớ những khoảng trống nào có thể bỏ qua ...
phroureo

Hầu hết thời gian bạn có thể bỏ qua khoảng trắng ở giữa chữ và biến / từ khóa, vì chúng không thể bắt đầu bằng một chữ số.
Jonathan Frech

1

Ruby, 46 byte

Tôi thực sự nên loại bỏ vòng lặp while bằng một vòng lặp thay thế.

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

Chỉnh sửa: Cảm ơn @manatwork đã cạo sạch 1 byte!

Edit2: Cảm ơn @histocraft về 9 byte điên rồ!

Chỉnh sửa: Cảm ơn @manatwork một lần nữa vì đã loại bỏ 7 byte!


z!=z[/[01]+/]ngắn hơn z[/[^01]/]thậm chí còn ngắn hơn.
manatwork

@manatwork Cảm ơn! Ít hơn 1 byte!
Peter Lenkefi

2
Các dòng đơn trong khi các vòng lặp có xu hướng ngắn nhất:z="#{n.to_i*k+=1}"while z[/[^01]/]
lịch sử

@histocrat Đó là 9 byte! Và tôi thậm chí không biết rằng ruby ​​có khả năng này. Cảm ơn!
Peter Lenkefi

Điều thú vị là bạn không thay đổi thử nghiệm thành bộ ký tự bị phủ định sau đó được đề xuất lần thứ 2. Có lý do gì không?
manatwork

1

Scala, 114 byte

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

Phiên bản dễ đọc

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

1

lực lượng vũ phu gawk4, 28 + 2 = 30 byte

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

Cần phải được gọi với -M tùy chọn sử dụng số lớn. Tất nhiên điều này là chậm một cách lố bịch, sử dụng số lượng lớn thậm chí còn làm chậm nó hơn, nhưng về mặt lý thuyết thì đầu vào không bị giới hạn và việc sử dụng RAM là không đáng kể.

Ví dụ sử dụng (nếu bạn có thời gian để lãng phí ;))

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

gawk4 được tối ưu hóa, 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

Chà, cuối cùng thì đây là một bản sao câu trả lời của aditsu. Sau khi xem câu hỏi này, tôi vẫn đang tìm cách viết mã cho phần tổng hợp con, khi tôi không thể cưỡng lại việc xem các câu trả lời khác ở đây.

Trong các phần tử mảng awk có hành vi (lạ?) Mà nếu bạn so sánh một phần tử không tồn tại với một phần tử nào đó thì nó được khởi tạo bằng cách nào đó trống rỗng trước khi được so sánh (tôi sẽ thừa nhận rằng tôi không chắc chắn về những gì đang xảy ra ở đó). Vì vậy, sau khi kiểm tra !a[0]cácfor(i in a) vòng lặp bắt đầu ngay cả khi không khởi tạo a[$0]để0 như aditsu đã làm.

Dĩ nhiên -M tùy chọn cũng phải được sử dụng cho việc này.

Mặc dù nó khá nhanh nhưng nó vẫn chậm hơn đáng kể so với Python. Đối với 79992điều này mất khoảng 14 giây trên Core2Duo 2GHz của tôi. Và tôi sẽ không nói rằng nó hoạt động cho đầu vào lên đến 2 ^ 31, vì trong trường hợp xấu nhất, nó phải xây dựng một dãy số lớn (gawk4 sử dụng GMP cho điều này), có kích thước của số đầu vào. Vì một mảng lớn 'tiền thưởng' rất chậm trong ...


1

Thuốc nhuộm APL , 25

Điều này xác định một chương trình thích hợp "P" (không chỉ là một hàm không tên):

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

2∘bắt đầu bằng 2 là đối số bên trái
0::nếu có bất kỳ lỗi nào ...
⍵∇⍨1+⍺hãy gọi chính nó bằng một đối số bên trái tăng dần
⍺×⍵nhân các đối số bên trái và bên phải
thành chuỗi
⍎¨làm cho mỗi ký tự thành một số
~cố gắng logic (nếu thất bại, hãy xử lý lỗi ở trên, khác ...)
⍺⊣trả về đối số bên trái hiện tại.

      P 2
50
      P 21
481
      P¨⍳8    ⍝ 1 through 8
10 5 37 25 2 185 143 125
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.