Cho r và n, tìm n số đầu tiên của x trong đó di chuyển chữ số đầu tiên của x sang số cuối cho x / r = y


11

Mục tiêu

Đưa ra đầu vào rntìm các nsố tự nhiên đầu tiên xsao cho nếu chúng ta xoay chữ số đầu tiên đến vị trí cuối cùng chúng ta có được x/r.

Bạn có thể cho rằng 2 <= r <= 91 <= n <= 65535.

Bạn có thể viết một chương trình lấy đầu vào từ stdin hoặc đối số dòng lệnh; hoặc bạn có thể viết một hàm lấy rnlàm tham số. Đầu ra, tuy nhiên, nên được xuất chuẩn. Đầu ra phải là một dòng trên mỗi giá trị x, được định dạng theo x/r=ythứ tự tăng dần x.

Giải pháp của bạn phải có khả năng xử lý tất cả các trường hợp hợp lệ trong vòng một phút trên máy tính để bàn hợp lý.

Các trường hợp thử nghiệm

Đầu vào: 4 5
Đầu ra:

102564/4=25641  
205128/4=51282  
307692/4=76923  
410256/4=102564  
512820/4=128205

Đầu vào: 5 1
Đầu ra:714285/5=142857

Đây là mã golf, vì vậy ít byte nhất sẽ giành chiến thắng. Câu trả lời chiến thắng sẽ được chấp nhận 4 tuần kể từ bây giờ (2014-09-19).

Tín dụng cho câu hỏi này đi đến đồng nghiệp của tôi, người cho phép tôi đăng câu hỏi này tại đây :)


Hạn chế thời gian là khó khăn với số lượng đầu ra cần thiết. Theo đó gprof, một trường hợp đầu vào cho chương trình của tôi dành ít hơn nửa giây trong mã của tôi, nhưng mất khoảng 80 giây, mà tôi cho rằng chủ yếu phải chặn đầu ra.
aschepler

Ah, tôi đã vượt qua nó bằng cách tránh printf.
aschepler

Câu trả lời:


7

Haskell, 182 179

Phiên bản thứ hai, có thể chơi được nhiều hơn, nhưng với thuật toán "thích hợp" lần này. Cụ thể, nó hoàn thành trong vòng vài phút với r=4n=65535, nhưng một lần nữa, máy tính của tôi không hợp lý cũng không phải máy tính để bàn, vì vậy rất có thể điều này sẽ tồn tại trong vòng một phút trên các máy khác.

n#r=take n$[s(10^k*a+d)++'/':s r++'=':s d++s a|k<-[0..],a<-[1..9],let(d,m)=divMod(a*(10^k-r))(10*r-1),m<1]
s=show
main=interact$unlines.(\(r:n:_)->n#fromIntegral r).map read.words

Nó dựa trên ý tưởng rằng x=10^k*a + m, nơi chữ số đầu tiên của nó 0≤a≤9được di chuyển đến cuối để có được y=10*m+a. Một toán nhỏ cho thấy mcó thể thu được như a*(10^k-r)/(10*r-1), vì vậy chúng tôi chỉ đơn giản là quét aqua [1..9]cho mỗi ktừ 0 đến vô cùng, và giữ và in đầu tiên nkết quả mà biểu thức trên cho mlà không thể thiếu.

Điều fromIntegralnày là bắt buộc bởi vì readmột danh sách với nmột trong các yếu tố của nó main, kết hợp với việc sử dụng nin take, sẽ buộc rphải Intxuyên suốt, dẫn đến tràn đầy khó chịu với những con số lớn trong câu hỏi. Tôi có thể đã sử dụng genericTake, nhưng điều đó đòi hỏi một import.

Mã này cũng có lợi ích là gần như tầm thường để mở rộng sang các cơ sở khác ngoài 10.

Đầu vào được đọc từ stdin, hai giá trị có thể được phân tách bằng bất kỳ khoảng trắng nào.


Mã của bạn sẽ ngắn hơn nếu bạn thoát khỏi các backsticks
tự hào

@proudhaskeller: không chắc chắn vì không có dấu ngoặc đơn xung quanh chúng để tách toán tử và toán hạng mà không yêu cầu khoảng trắng.
TheSpiniteInquisition

Tôi không thể đọc Haskell, vì vậy tôi không hoàn toàn chắc chắn những gì bạn đang làm. Điều này sẽ giải quyết r = 5; n = 65535trong vòng một phút?
Martin Ender

@ MartinBüttner: Tôi đã chờ nhận xét đó. Vâng, nó có thể sẽ, nhưng thực tế không phải trên máy tính của tôi (hoặc bất kỳ ai khác ngay bây giờ, trên thực tế). Vấn đề cần một thuật toán tiên tiến hơn, tôi nghĩ vậy. :(
TheSpiniteInquisition

@TheSpiniteInquisition Nhưng bạn có thể thay thế y`mod`10bằng mod y10, đó là một char ngắn hơn
tự hào

1

Pure Bash (không có tiện ích bên ngoài), 80 byte

for((;++x,c<$2;));{
y=$[10#${x:1}${x:0:1}]
((y*$1==x))&&echo $x/$1=$y&&((c++))
}

Lưu ý bash chỉ thực hiện số học số nguyên và không dấu phẩy động, vì vậy chúng tôi kiểm tra nếu x == y * rthay vì x / r == y. Ngoài ra phép nhân thường sẽ nhanh hơn. Tuy nhiên, đây không phải là nơi đáp ứng yêu cầu hiệu suất.

Đầu ra:

$ ./rotdiv.sh 4 5
102564/4=25641
205128/4=51282
307692/4=76923
410256/4=102564
512820/4=128205
$ ./rotdiv.sh 5 1
714285/5=142857
$ 

1

C 468

#include <stdlib.h>
#include <stdio.h>
#define a(s)fputs(s,stdout);
#define b(c)putchar(c);
int r;int z(char*s,int m){for(int i=0;i++<=m;)a(s)b(47)b(r+48)b(61)char*t=s;
while(*++t==48);a(t)while(m--)a(s)b(*s)b(10)}char x[10][60];
int main(int c,char**v){r=atoi(v[1]);int n=atoi(v[2]),q=10*r-1,d=0,p;
while(d++<9){p=r*d;char*y=x[d];do{p*=10;*y++=p/q+48;p%=q;}while(p!=r*d);}
d=1;p=q=0;while(n--){r==5&p<6?z(x[7],7*q+p++):(z(x[d],(r==5&d==7)?7*q+6:q),
++d>9?q+=d=1,p=0:0);}}

(Một số dòng mới không được tính trong số byte đã được thêm ở trên để loại bỏ các thanh cuộn. Có, dòng mới cuối cùng được tính.)

Mong đợi các đối số trên dòng lệnh và giả sử đầu ra tiêu chuẩn chấp nhận ASCII. Thời gian chạy là O (số lượng đầu ra byte) = O (n * n).

Không, tôi không thể sử dụng printf. Điều đó làm mất quá nhiều thời gian và đẩy chương trình vượt quá giới hạn phút trên máy tính để bàn của tôi. Như vậy, một số trường hợp thử nghiệm mất khoảng 30 giây.

Thuật toán coi đầu ra là các chuỗi, không phải là số, vì chúng nhanh chóng trở nên to lớn và có các mẫu mạnh trong đầu ra.

Hơi vô dụng:

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

/* r is as in the problem description */
int r;

void show_line(const char* num, int repeats) {
    for (int i=0; i <= repeats; ++i)
        fputs(num, stdout);
    printf("/%c=", '0'+r);

    /* Assume the repeated num is a solution. Just move the first
       digit and skip any resulting leading zeros. */
    const char* num_tail = num;
    ++num_tail;
    while (*num_tail=='0')
        ++num_tail;
    fputs(num_tail, stdout);
    while (repeats--)
        fputs(num, stdout);
    printf("%c\n", *num);
}

/* sol[0] is unused. Otherwise, sol[d] is the repeating digits in the
   decimal representation of (r*d)/(10*r-1). */
char sol[10][60];

int main(int argc, char** argv) {
    r = atoi(argv[1]);
    int n = atoi(argv[2]);
    int q = 10*r-1;
    int d = 0;

    /* Populate the strings in sol[]. */
    while (d++<9) {
        int p = r*d;
        char* sol_str = sol[d];

        /* Do the long division p/q in decimal, stopping when the remainder
           is the original dividend. The integer part is always zero. */
        do {
            p *= 10;
            *sol_str++ = p/q + '0';
            p %= q;
        } while (p != r*d);
    }

    /* Output the answers. */
    d = 1;
    int repeats = 0;
    int r5x7_repeats = 0;
    while (n--) {
        if (r==5 && r5x7_repeats<6) {
            show_line(x[7], 7*repeats + r5x7_repeats);
        } else {
            if (r==5 && d==7)
                show_line(x[d], 7*repeats + 6);
            else
                show_line(x[d], repeats);
            if (++d > 9) {
                d = 1;
                ++repeats;
                r5x7_repeats = 0;
            }
        }
    }
}

Bằng chứng

chương trình giải quyết vấn đề:

(Trong bằng chứng, lấy tất cả các toán tử và hàm là các hàm toán học thực sự, không phải là các phép toán máy tính gần đúng với chúng. ^Biểu thị lũy thừa, không phải là xor bitwise.)

Để rõ ràng, tôi sẽ sử dụng một hàm ToDecđể mô tả quá trình viết số thông thường dưới dạng một chuỗi các chữ số thập phân. Phạm vi của nó là tập hợp các bộ dữ liệu được đặt hàng trên {0...9}. Ví dụ,

ToDec(2014) = (2, 0, 1, 4).

Đối với một số nguyên dương n, xác định L(n)là số chữ số trong biểu diễn thập phân của n; hoặc là,

L(n) = 1+floor(log10(n)).

Đối với một số nguyên dương kvà một số nguyên không âm nvới L(n)<k, hãy xác định Rep_k(n)là số thực có được bằng cách thêm các số 0 ở trước các chữ số thập phân của n, nếu cần để lấy ktổng các chữ số, sau đó lặp lại vô hạn các kchữ số đó sau dấu thập phân. Ví dụ

Rep_4(2014) = .201420142014...
Rep_5(2014) = .020140201402...

Nhân Rep_k(n) * 10^kcho các chữ số ntrước dấu thập phân và chữ số (không đệm) được nlặp lại vô hạn sau dấu thập phân. Vì thế

Rep_k(n) * 10^k = n + Rep_k(n)
Rep_k(n) = n / (10^k - 1)

Cho một số nguyên dương r, giả sử xlà một giải pháp cho vấn đề và

ToDec(x) = ( x_1, x_2, ..., x_k )

ở đâu x_1 != 0k = L(x).

Là một giải pháp, xlà bội số của r, và

ToDec(x/r) : ( x_2, x_3, ..., x_k, x_1 ).

Áp dụng Rep_khàm cho một phương trình tốt đẹp:

10*Rep_k(x) = x_1 + Rep_k(x/r)

Sử dụng hình thức đóng của nó từ phía trên,

10x / (10^k - 1) = x_1 + x / r / (10^k - 1)
x = x_1 * r * (10^k-1) / (10r - 1)

x_1phải nằm trong bộ {1 ... 9}. rđã được chỉ định là trong tập hợp {2 ... 9}. Bây giờ câu hỏi duy nhất là, với giá trị knào của công thức trên để xcho một số nguyên dương? Chúng tôi sẽ xem xét từng giá trị có thể của rcá nhân.

Khi r= 2, 3, 6, 8 hoặc 9, lần lượt 10r-1là 19, 29, 59, 79 hoặc 89. Trong mọi trường hợp, mẫu số p = 10r-1là số nguyên tố. Trong tử số, chỉ 10^k-1có thể là bội số p, xảy ra khi

10^k = 1 (mod p)

Tập hợp các giải pháp được đóng dưới phép cộng và phép trừ không dẫn đến số âm. Vì vậy, tập hợp bao gồm tất cả các bội số của một số yếu tố phổ biến, cũng là giải pháp ít tích cực nhất cho k.

Khi nào r = 410r-1 = 39; hoặc khi r = 710r-1 = 69, mẫu số là 3 lần một số nguyên tố khác nhau p=(10r-1)/3. 10^k-1luôn là bội số của 3 và một lần nữa, không có yếu tố nào khác trong tử số có thể là bội số của p, do đó, một lần nữa vấn đề giảm xuống

10^k = 1 (mod p)

và một lần nữa các giải pháp là tất cả các bội số của giải pháp ít tích cực nhất cho k.

[Chưa xong...]


0

Con trăn - 91 90

Đây là phát súng đầu tiên:

r,n=input();i=1
while n:
 if int(`i`[1:]+`i`[0])*r==i:print'%d/%d=%d'%(i,r,i/r);n-=1
 i+=1

Chỉnh sửa: Ok, có lẽ cách chậm để đáp ứng giới hạn thời gian 1 phút cần thiết cho các số 65K.


1
Bạn đã thử nghiệm điều này chống lại yêu cầu hiệu suất?
Peter Taylor

2
Tôi có nghi ngờ rằng điều này sẽ tìm thấy 65k số như vậy trước khi mặt trời nổ tung.
Martin Ender

0

JavaScript - 145

function f(a,b){for(d=0;d<b;d++)for(i=1;;i++){c=i/a;if(c==parseInt(i.toString().substring(1)+i.toString().charAt(0)))console.log(i+'/'+a+'='+c)}}

không chơi gôn

function f(a,b){
    for(d=0;d<b;d++) //loop for the right amount
        for(i=1;;i++){ //iterating loop
            c=i/a; //actual result of the division
            if(c==parseInt(i.toString().substring(1)+i.toString().charAt(0)))
                console.log(i+'/'+a+'='+c)
        }
}

Tôi không thể làm điều này hoạt động được, nhưng ngay cả khi nó sẽ, tôi nghi ngờ nó sẽ đáp ứng yêu cầu về hiệu suất.
Martin Ender

@ MartinBüttner nó hoạt động hoàn toàn tốt cho tôi. có thể là nó không đáp ứng các yêu cầu về hiệu năng nhưng máy tính của tôi hiện tại khá yếu ... Bạn đã làm gì để đoạn mã này hoạt động?
Armin

1
Sao chép nó vào bàn điều khiển và nối thêm (5,4). Lý do nó không hoạt động là vì số lượng phát triển rất lớn. a) Lớn hơn nhiều so với một số trong JS có thể biểu thị chính xác và b) quá lớn vì nó có thể khả thi để lặp qua tất cả các số để đến đó.
Martin Ender

0

Python 3 - 223 179 byte

Python triển khai giải pháp của TheSpanishInquisition:

r,n=map(int,input().split());k=0
while 1:
 for a in range(1,10):
  D,M=divmod(a*(10**k-r),10*r-1)
  if M==0:
   print("%d/%d=%d"%(a*10**k+D,r,10*D+a));n-=1
   if n==0:exit()
 k+=1

Chạy:

  • python3 <whatever you named it>.py
  • Đưa đầu vào vào stdin
  • Không gian đầu vào tách biệt

Đầu ra:

$python3 <whatever you named it>.py
4 8
102564/4=25641
205128/4=51282
307692/4=76923
410256/4=102564
512820/4=128205
615384/4=153846
717948/4=179487
820512/4=205128

Kết quả:

https://oeis.org/A092697 là giá trị đầu tiên cho mỗi r.

Dường như chỉ có một số giá trị nhất định của k tạo ra câu trả lời và khoảng thời gian là thường xuyên. Ví dụ: r = 4:

Form: k [a, a, ...]
0 []
1 []
2 []
3 []
4 []
5 [1, 2, 3, 4, 5, 6, 7, 8, 9]
6 []
7 []
8 []
9 []
10 []
11 [1, 2, 3, 4, 5, 6, 7, 8, 9]
12 []
13 []
14 []
15 []
16 []
17 [1, 2, 3, 4, 5, 6, 7, 8, 9]
18 []
19 []
20 []
21 []
22 []
23 [1, 2, 3, 4, 5, 6, 7, 8, 9]

Các khoảng là:

  • 2 = 18
  • 3 = 28
  • 4 = 6
  • 5 = 6 (5 dường như là một sự bất thường, vì đối với hầu hết các giá trị của r, có các cụm 9, 5 dạng của 9 và 1 (chỉ có a = 7 hoạt động), xem bên dưới)
  • 6 = 58
  • 7 = 22
  • 8 = 13
  • 9 = 44

Mẫu này https://oeis.org/A094224 .

Sử dụng các giá trị này, một phiên bản hiệu quả hơn có thể được xây dựng:

import math

def A094224(n):
    return [18,28,6,6,58,22,13,44][n-2]


r,n=map(int,input().split());k=A094224(r)-1
H={}
while 1:
    for a in range(1,10):
        D,M=divmod(a*10**k-a*r,10*r-1)
        if M==0:
            print("%d/%d=%d"%(a*10**k+D,r,10*D+a));n-=1
            if n==0:exit()
    k+=A094224(r)

Tuy nhiên, tôi không thể (chưa) chứng minh rằng điều này tiếp tục về mặt toán học.

Kết quả cho r = 5:

0 []
1 []
2 []
3 []
4 []
5 [7]
6 []
7 []
8 []
9 []
10 []
11 [7]
12 []
13 []
14 []
15 []
16 []
17 [7]
18 []
19 []
20 []
21 []
22 []
23 [7]
24 []
25 []
26 []
27 []
28 []
29 [7]
30 []
31 []
32 []
33 []
34 []
35 [7]
36 []
37 []
38 []
39 []
40 []
41 [1, 2, 3, 4, 5, 6, 7, 8, 9]

2
Bạn đã thử nó với đầu vào 9 65535?
Peter Taylor

Tôi có lẽ nên sử dụng unsigned long longcho điều đó, và làm cho nó đa lõi để làm điều đó trong một phút.
matjoyce

1
Nếu unsigned long longlà 64 bit, nó không đủ lớn.
Peter Taylor

Đúng, tôi đã chuyển sang giải pháp của @ TheSp BiếnInquisition và sử dụng python thay thế.
matjoyce
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.