เมื่อรับ r และ n ให้หาตัวเลข n แรกของ x โดยที่การเลื่อนตำแหน่งแรกของ x ไปยังสุดจะให้ x / r = y


11

วัตถุประสงค์

ได้รับการป้อนข้อมูลrและnพบว่าคนแรกที่nหมายเลขธรรมชาติเช่นว่าถ้าเราหมุนหลักแรกไปยังสถานที่สุดท้ายที่เราได้รับxx/r

คุณอาจจะคิดว่าและ2 <= r <= 91 <= n <= 65535

คุณสามารถเขียนโปรแกรมที่รับอินพุตจากอาร์กิวเมนต์ stdin หรือ command-line; หรือคุณอาจเขียนฟังก์ชั่นที่ใช้rและnเป็นพารามิเตอร์ อย่างไรก็ตามเอาต์พุตควรเป็น stdout เอาท์พุทควรจะเป็นหนึ่งบรรทัดต่อมูลค่าของxในรูปแบบในการสั่งซื้อที่เพิ่มขึ้นของx/r=yx

โซลูชันของคุณจะต้องสามารถจัดการกรณีที่ถูกต้องทั้งหมดภายในหนึ่งนาทีบนคอมพิวเตอร์เดสก์ท็อปที่เหมาะสม

กรณีทดสอบ

อินพุต: 4 5
เอาต์พุต:

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

อินพุต: 5 1
เอาต์พุต:714285/5=142857

นี่คือ code-golf ดังนั้นอย่างน้อยไบต์จะชนะ คำตอบที่ชนะจะได้รับการยอมรับ 4 สัปดาห์นับจากนี้ (2014-09-19)

เครดิตสำหรับคำถามนี้ไปที่เพื่อนร่วมงานของฉันที่อนุญาตให้ฉันโพสต์คำถามนี้ได้ที่นี่ :)


การ จำกัด เวลาทำได้ยากด้วยจำนวนเอาต์พุตที่ต้องการ ตามgprofกรณีการป้อนข้อมูลหนึ่งรายการสำหรับโปรแกรมของฉันใช้เวลาน้อยกว่าครึ่งวินาทีในรหัสของฉัน แต่ใช้เวลาทั้งหมดประมาณ 80 วินาทีซึ่งฉันคิดว่าต้องปิดกั้นเอาต์พุตเป็นส่วนใหญ่
aschepler

printfอาผมได้รอบโดยการหลีกเลี่ยง
aschepler

คำตอบ:


7

Haskell, 182 179

รุ่นที่สองน่าจะเล่นได้ง่ายขึ้น แต่ด้วยอัลกอริทึม "เหมาะสม" โดยเฉพาะอย่างยิ่งมันจะเสร็จสิ้นภายในไม่กี่นาทีด้วยr=4และn=65535แต่อีกครั้งคอมพิวเตอร์ของฉันก็ไม่สมเหตุสมผลหรือเดสก์ท็อปดังนั้นโอกาสนี้จะอยู่ภายในหนึ่งนาทีบนเครื่องอื่น ๆ

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

มันขึ้นอยู่กับความคิดที่ว่าx=10^k*a + mที่หลักแรกของมันจะถูกย้ายไปยังจุดสิ้นสุดที่จะได้รับ0≤a≤9 y=10*m+aคณิตศาสตร์เล็ก ๆ น้อย ๆ เผยให้เห็นว่าmสามารถรับได้เป็นa*(10^k-r)/(10*r-1)ดังนั้นเราเพียงแค่สแกนaมากกว่า[1..9]ทุกkจาก 0 ถึงอินฟินิตี้และเก็บและพิมพ์ครั้งแรกnผลที่แสดงออกข้างต้นสำหรับmเป็นส่วนประกอบสำคัญ

fromIntegralถูกต้องเนื่องจากreadไอเอ็นจีรายการกับnเป็นหนึ่งในองค์ประกอบในการmainในการรวมกันที่มีการใช้nในการtakeจะบังคับให้rไปIntตลอดซึ่งผลในการล้นที่น่ารังเกียจกับตัวเลขใหญ่ในคำถาม ฉันจะได้ใช้แต่ที่จำเป็นต้องใช้genericTakeimport

รหัสนี้ยังมีประโยชน์ในการขยายไปสู่ฐานที่ไม่ใช่ 10

อินพุตถูกอ่านจากstdinทั้งสองค่าสามารถคั่นด้วยช่องว่างใด ๆ


รหัสของคุณควรสั้นกว่านี้หากคุณกำจัดแบคโฮออก
ภาคภูมิใจ Haskeller

@proudhaskeller: ไม่แน่ใจเพราะไม่มีวงเล็บอยู่รอบ ๆ เพื่อแยกตัวดำเนินการและตัวถูกดำเนินการโดยไม่ต้องเว้นวรรค
TheSpanishInquisition

ฉันอ่าน Haskell ไม่ได้ดังนั้นฉันไม่แน่ใจว่าคุณกำลังทำอะไรอยู่ จะแก้ปัญหานี้r = 5; n = 65535ภายในหนึ่งนาทีหรือไม่
Martin Ender

@ MartinBüttner: ฉันกำลังรอความคิดเห็นนั้น ใช่มันอาจเป็นไปได้ แต่ไม่ใช่ในคอมพิวเตอร์ของฉัน (หรือในความเป็นจริงตอนนี้) ปัญหาต้องการอัลกอริทึมขั้นสูงกว่าฉันคิดว่า :(
TheSpanishInquisition

@TheSpanishInquisition แต่คุณจะสามารถแทนที่y`mod`10ด้วยmod y10ซึ่งเป็นถ่านที่สั้นกว่า
ภูมิใจ haskeller

1

Pure Bash (ไม่มียูทิลิตี้ภายนอก), 80 ไบต์

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

หมายเหตุทุบตีเพียง แต่จำนวนเต็มเลขคณิตจุดและไม่ลอยเพื่อให้เราตรวจสอบว่าแทนx == y * r x / r == yการคูณด้วยโดยทั่วไปควรเร็วกว่า ถึงกระนั้นก็ยังไม่มีที่ไหนใกล้เคียงกับข้อกำหนดด้านประสิทธิภาพ

เอาท์พุท:

$ ./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);}}

(มีการเพิ่มบรรทัดใหม่ที่ไม่นับในจำนวนไบต์ด้านบนเพื่อกำจัดแถบเลื่อนใช่การขึ้นบรรทัดใหม่สุดท้ายจะถูกนับ)

คาดหวังข้อโต้แย้งในบรรทัดคำสั่งและถือว่าเอาต์พุตมาตรฐานยอมรับ ASCII รันไทม์คือ O (จำนวนไบต์เอาท์พุท) = O (n * n)

printfไม่ฉันไม่สามารถใช้ ใช้เวลามากเกินไปและผลักโปรแกรมเกินขีด จำกัด นาทีบนเดสก์ท็อปของฉัน เนื่องจากเป็นกรณีทดสอบบางกรณีใช้เวลาประมาณ 30 วินาที

อัลกอริทึมปฏิบัติกับผลลัพธ์เป็นสตริงไม่ใช่ตัวเลขเนื่องจากมีจำนวนมหาศาลอย่างรวดเร็วและมีรูปแบบที่แข็งแกร่งในเอาต์พุต

ค่อนข้างอวดดี:

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

พิสูจน์

ว่าโปรแกรมแก้ปัญหา:

(ในหลักฐานที่ใช้ประกอบการทั้งหมดและฟังก์ชั่นที่จะเป็นฟังก์ชั่นทางคณิตศาสตร์ที่จริงไม่ได้การดำเนินงานคอมพิวเตอร์ที่ใกล้เคียงกับพวกเขา. ^หมายถึงการยกกำลังไม่ xor บิต.)

เพื่อความชัดเจนฉันจะใช้ฟังก์ชันToDecเพื่ออธิบายกระบวนการทั่วไปของการเขียนตัวเลขเป็นลำดับเลขทศนิยม ช่วงคือชุดของ tuples {0...9}สั่งซื้อบน ตัวอย่างเช่น,

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

สำหรับจำนวนเต็มบวกnกำหนดL(n)ให้เป็นจำนวนหลักในการแทนทศนิยมของn; หรือ,

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

สำหรับจำนวนเต็มบวกkและจำนวนเต็มไม่เป็นลบnด้วยL(n)<kให้นิยามRep_k(n)เป็นจำนวนจริงที่ได้รับโดยการเพิ่มศูนย์หน้าตัวเลขทศนิยมnถ้าจำเป็นเพื่อให้ได้kผลรวมตัวเลขแล้วซ้ำkตัวเลขเหล่านั้นซ้ำหลังจุดทศนิยม เช่น

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

การคูณRep_k(n) * 10^kจะให้ตัวเลขnก่อนจุดทศนิยมและตัวเลข (ศูนย์เป็นศูนย์) ของการnทำซ้ำอย่างไม่สิ้นสุดหลังจุดทศนิยม ดังนั้น

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

รับจำนวนเต็มบวกrสมมติว่าxเป็นวิธีแก้ปัญหาและ

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

ที่และx_1 != 0k = L(x)

จะเป็นวิธีการแก้ไขxเป็นหลายตัวrและ

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

การใช้Rep_kฟังก์ชันให้สมการที่ดี:

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

ใช้แบบฟอร์มที่ปิดจากด้านบน

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

x_1{1 ... 9}จะต้องอยู่ในชุด ถูกระบุว่าจะอยู่ในชุดr {2 ... 9}ตอนนี้คำถามเดียวก็คือว่าkสูตรข้างต้นxมีค่าเป็นจำนวนเต็มบวกเท่าใด เราจะพิจารณาแต่ละค่าที่เป็นไปได้ของrแต่ละรายการ

เมื่อr= 2, 3, 6, 8, หรือ 9, 10r-1คือ 19, 29, 59, 79, หรือ 89 ตามลำดับ ในทุกกรณีส่วนที่p = 10r-1เป็นนายก ในตัวเศษ10^k-1สามารถมีได้หลายตัวpเท่านั้นซึ่งจะเกิดขึ้นเมื่อ

10^k = 1 (mod p)

ชุดของการแก้ปัญหาถูกปิดภายใต้การบวกและภายใต้การลบที่ไม่ส่งผลให้จำนวนลบ kดังนั้นชุดประกอบด้วยหลายทั้งหมดของบางปัจจัยร่วมกันซึ่งยังเป็นวิธีการแก้ปัญหาในเชิงบวกอย่างน้อยสำหรับ

เมื่อไหร่r = 4และ10r-1 = 39; หรือเมื่อr = 7และ10r-1 = 69หารคือ 3 p=(10r-1)/3ครั้งสำคัญที่แตกต่างกัน 10^k-1เป็นผลคูณของ 3 เสมอและไม่มีปัจจัยอื่นใดในตัวเศษที่สามารถคูณได้pอีกครั้งดังนั้นปัญหาจึงลดลง

10^k = 1 (mod p)

kและอีกครั้งการแก้ปัญหาที่มีทั้งหมดหลายของการแก้ปัญหาในเชิงบวกน้อยสำหรับ

[ยังไม่เสร็จ...]


0

Python - 91 90

นี่เป็นภาพแรก:

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

แก้ไข:ตกลงอาจเป็นไปได้ที่จะช้าเพื่อให้ตรงตามเวลาที่กำหนด 1 นาทีสำหรับตัวเลข 65K


1
คุณได้ทดสอบสิ่งนี้กับความต้องการด้านประสิทธิภาพหรือไม่?
Peter Taylor

2
ฉันมีข้อสงสัยว่าจะพบตัวเลขดังกล่าว 65k ก่อนที่ดวงอาทิตย์จะระเบิด
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)}}

ไม่ golfed:

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

ฉันไม่สามารถทำให้มันทำงานได้เลย แต่ถึงจะเป็นเช่นนั้นฉันก็สงสัยว่ามันจะเป็นไปตามข้อกำหนดด้านประสิทธิภาพ
Martin Ender

@ MartinBüttnerมันใช้งานได้ดีอย่างสมบูรณ์แบบสำหรับฉัน อาจเป็นไปได้ว่ามันไม่เป็นไปตามข้อกำหนดด้านประสิทธิภาพ แต่ฉันเป็นคอมพิวเตอร์ที่ตอนนี้ฉันค่อนข้างอ่อนแอ ... คุณทำอะไรเพื่อให้โค้ดชิ้นนี้ทำงาน?
Armin

1
(5,4)คัดลอกลงในคอนโซลและท้าย เหตุผลที่จะไม่ทำงานคือว่าตัวเลขที่เติบโตมากขนาดใหญ่ ก) จำนวนที่มากเกินกว่าจำนวนใน JS สามารถแสดงได้อย่างถูกต้องและ b) มีขนาดใหญ่เกินไปเนื่องจากเป็นไปได้ที่จะวนซ้ำผ่านตัวเลขทั้งหมดเพื่อไปที่นั่น
Martin Ender

0

Python 3 - 223 179 ไบต์

การใช้งาน Python ของโซลูชัน 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

วิ่ง:

  • python3 <whatever you named it>.py
  • ใช้อินพุตบน stdin
  • คั่นพื้นที่อินพุต

เอาท์พุท:

$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

ผลการวิจัย:

https://oeis.org/A092697เป็นค่าแรกสำหรับแต่ละ r

ดูเหมือนว่ามีเพียงค่าบางค่าของ k เท่านั้นที่ให้คำตอบและช่วงเวลานั้นเป็นปกติ เช่นสำหรับ 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]

ช่วงเวลาคือ:

  • 2 = 18
  • 3 = 28
  • 4 = 6
  • 5 = 6 (5 ดูเหมือนว่าจะเป็นความผิดปกติสำหรับค่าส่วนใหญ่ของ r มีกลุ่มที่ 9, 5 รูปแบบกลุ่มที่ 9 และ 1 (มีเพียง = 7 ทำงาน) ดูด้านล่าง)
  • 6 = 58
  • 7 = 22
  • 8 = 13
  • 9 = 44

รูปแบบนี้https://oeis.org/A094224

เมื่อใช้ค่าเหล่านี้จะสามารถสร้างเวอร์ชันที่มีประสิทธิภาพมากขึ้น:

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)

อย่างไรก็ตามฉันยังไม่สามารถพิสูจน์ได้ว่าสิ่งนี้ยังคงอยู่ในทางคณิตศาสตร์

ผลลัพธ์สำหรับ 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
คุณทดสอบด้วยอินพุต9 65535หรือไม่
Peter Taylor

ฉันอาจจะใช้unsigned long longสำหรับสิ่งนั้นและทำให้มันเป็นมัลติคอร์เพื่อทำสิ่งนั้นในหนึ่งนาที
matsjoyce

1
ถ้าunsigned long long64 บิตมันไม่ใหญ่พอ
Peter Taylor

จริงฉันเปลี่ยนไปใช้โซลูชันของ @ TheSpanishInquisition และใช้ python แทน
matsjoyce
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.