ช่วงเวลาของการแทนทศนิยม


16

เขียนฟังก์ชั่นซึ่งจะเป็นจำนวนเต็มบวกเดียวnและผลตอบแทนระยะเวลาของการแสดงทศนิยมของ 1 / n

กรณีทดสอบ:

1 -> 1               # 1/1 = 1.0000...... = 1._0
2 -> 1               # 1/2 = 0.5000...... = 0.5_0
3 -> 1               # 1/3 = 0.3333...... = 0._3
7 -> 6               # 1/7 = 0.14285714.. = 0._142857
13 -> 6
14 -> 6
123 -> 5
345 -> 22
654 -> 108
12345 -> 822
67890 -> 120

นี่คือรหัสกอล์ฟบิวด์อินหรือไลบรารี่ที่ส่งคืนระยะเวลาโดยตรงไม่ได้รับอนุญาต ตัวเลขที่มีอย่างน้อย 100,000 รายการควรทำงานภายในเวลาที่เหมาะสม (อย่างน้อยหลายนาที)


คำถามระบุว่า "ตัวเลขสูงถึง 100,000 อย่างน้อยควรทำงานภายในเวลาที่เหมาะสม" แต่โปรแกรมจะต้องให้คำตอบที่ถูกต้องสำหรับตัวเลขที่มีขนาดใหญ่กว่านี้หรือไม่? หรือว่าจะยอมรับการใช้อัลกอริทึมที่มีความแม่นยำถึง 100000 เท่านั้น
FireFly

1
@FireFly อัลกอริทึมต้องให้คำตอบที่ถูกต้อง
Howard

2
ทำไม 1 ถึงคืน 1 ฉันจะคิดว่า 0?
Timtech

@Timtech1.00000000000000000000000000000000000
Cruncher

@ Cruncher โอ้ขอบคุณฉันได้รับแล้ว
Timtech

คำตอบ:


11

APL, 19 ตัวอักษร / ไบต์ *

{(↑⍳⍨1∘↓)⌽⍵|10x*⍳⍵}

Nars2000 รุ่นก่อนหน้านี้ผิดกับตัวเลขบางตัวมันควรจะถูกต้อง ฉันตรวจสอบด้วยตนเองในทุกหมายเลขมากถึง 50

อีกครั้งเครดิตไปที่Ben Reichสำหรับความคิดของการดูระยะเวลา10^i (mod x)

มุมมองการระเบิด

{                     ⍳⍵}   generate all naturals up to the argument ⍵
                 10x*       raise 10 to each of them, with unlimited precision
              ⍵|            compute the respective remainders mod ⍵
            ⌽               reverse the list
 (  ⍳⍨    )                 (fork) find the position of the first occurrence
  ↑                         of the fist element of the list
       1∘↓                  in the remainder of the list

ตัวอย่าง

      {(↑⍳⍨1∘↓)⌽⍵|10x*⍳⍵}¨1 2 3 7 13 14 123 345 654 12345 67890
1 1 1 6 6 6 5 22 108 822 120

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
*: APL สามารถเขียนด้วยชุดอักขระแบบไบต์เดียว (ดั้งเดิม) ของตัวเองที่จับคู่สัญลักษณ์ APL กับค่าบน 128 ไบต์ ดังนั้นเพื่อจุดประสงค์ในการให้คะแนนโปรแกรมของ N chars ที่ใช้อักขระ ASCII และสัญลักษณ์ APLเท่านั้นจึงถือได้ว่ามีความยาว N ไบต์


20ฉันไม่สามารถได้คำตอบที่ถูกต้องสำหรับการป้อนข้อมูลเช่น คุณช่วยยืนยันได้ไหม
Howard

ฉันทำตามตัวอย่างที่คุณโพสต์ ในตัวอย่างของคุณ 1/2 = 0.5 -> 1 ดังนั้นตามธรรมชาติ 1/20 = 0.05 -> 2. คุณได้อะไร
เบีย

คำตอบที่ถูกต้องจะเป็น 1 ตั้งแต่ 1/20 = 0.05_0_
Howard

ฉันเห็น. ให้ฉันฉันจะแก้ไขคำตอบของฉัน
เบีย

410 != 100 (mod 4)ดูเหมือนว่ามันจะให้คำตอบที่ผิดเกินไปเพราะ
ปีเตอร์เทย์เลอร์

7

GolfScript ( 42 27)

{:x)1\[{.10*x%}*]-1%(?)}:P;

เวลามาตรฐาน: 5 วินาที รหัสการเปรียบเทียบ:

'"The time is #{Time.now#1
}"'~ puts
[1 2 3 7 13 14 123 345 654 12345 67890 99991]{[P]p}%
'"The time is #{Time.now#2
}"'~ puts

10^i (mod x)เครดิตเบนรีคสำหรับแนวคิดหลักของการมองที่ระยะเวลาของ

คำอธิบาย

ระยะเวลาpที่ถูกกำหนดให้เป็นจำนวนเต็มบวกที่เล็กที่สุดเช่นว่าทุกที่มีขนาดใหญ่พอที่เรามีi เราสามารถลดความซับซ้อนที่เล็กน้อยเพื่อfrac(10^i * 1/x) = frac(10^(i+p) * 1/x) frac(10^i / x) = frac(10^(i+p) / x)ตอนนี้frac(a / x) = frac(b / x)IFF a == b (mod x)ดังนั้นเรากำลังมองหาจำนวนเต็มบวกที่เล็กที่สุดเช่นว่าทุกที่มีขนาดใหญ่พอที่:i10^i == 10^(i+p) (mod x)

10^i == 10^(i+p) (mod x)สมมติ จากนั้น10^(i+1) == 10 * 10^i == 10 * 10^(i+p) == 10^(i+p+1) (mod x); ดังนั้นเมื่อเราได้รับการกล่าวซ้ำเราก็อยู่ในวัฏจักรที่ไม่สามารถแตกหักได้

มีเพียง แต่มีxค่าที่แตกต่างกัน(mod x)ดังนั้นโดยหลักรังนกพิราบที่เราจะต้องได้รับการทำซ้ำในครั้งแรกที่ค่านิยมของx + 110^i (mod x)

ดังนั้นสิ่งที่โค้ดข้างต้นทำคือการคำนวณx + 2ค่าของ10^i (mod x)* แล้วอันสุดท้ายก็รับประกันได้ว่าจะเป็นการเกิดซ้ำและโดยการย้อนกลับรายการและค้นหามันฉันสามารถค้นหาเหตุการณ์ล่าสุด ยิ่งกว่านั้นเพราะฉันแค่ทำการค้นหาเพียงครั้งเดียวนี่คือเวลาที่ใช้หลอกเทียม

* หนึ่งเป็นพิเศษคือการจัดการกับกรณีพิเศษx = 1เพราะผมไม่ลด10^0 (mod x)และดังนั้นผมจึงต้องการจะมองหาใน0[1]


! น่ากลัว ฉันได้ลบคำตอบของฉันตั้งแต่ทางออกที่ดีกว่า! -
Ben Reich

7

Golfscript - 26 ไบต์

{:i.)+.,{;10*i%.}%i>|,}:f;

แก้ไข: อัปเดตเป็นเอาท์พุท1หากทศนิยมยุติลงแทนที่จะเป็นความยาวของการแทนทศนิยม

รุ่นที่ค่อนข้างมีประสิทธิภาพ ค่า67890ทำงานในเวลาประมาณ 10 วินาทีและ99991ประมาณ 20 วินาที มันช้ากว่าเมื่อก่อนเล็กน้อย (เร็วประมาณครึ่งหนึ่ง) เนื่องจากช่วงที่ทำซ้ำได้รับการเพิ่มขึ้นเป็นสองเท่าในช่วงครึ่งแรกซึ่งจะถูกละเว้น

ทางเลือกรวมถึง 26 ไบต์

{:i.)+.n*{*i%.}%i>)^^,}:f;

อันนี้ทำงานโดยการวนซ้ำสตริง"\n"*(2*i+1)ซึ่งiเป็นค่าที่ส่งผ่านไปยังฟังก์ชั่น ค่าที่ส่งผ่านไปยังบล็อกแต่ละครั้งเป็นค่าลำดับของ"\n"ซึ่งเป็น10

)^^เป็นบิตของการทำงานรอบ เมื่อคุณปลดอักขระออกจากสตริงผลลัพธ์จะเป็นค่าเลขลำดับของอักขระที่ถูกลบดังที่กล่าวไว้ข้างต้น อย่างไรก็ตามการต่อท้ายค่านั้นต่อท้ายจะผนวกการแสดงสตริงของตัวเลขนั้นมากกว่าตัวอักษร - พฤติกรรมที่ไม่สมมาตรอย่างเป็นธรรมและในความคิดของฉันมีข้อบกพร่องในการออกแบบ หากคุณต้องการทำเช่นนั้นจริงการสร้างสตริงก่อนจะเสียค่าใช้จ่ายเพียงหนึ่งไบต์

สำเนาพิเศษของค่าสุดท้ายนั้นมีอยู่แล้วในสแต็กดังนั้นฉันจึงลบค่าสุดท้ายอีกครั้ง)xor กับสตริงแล้ว xor อีกครั้งเพื่อให้ตัวละครที่ถูกเพิ่มหรือลบโดย xor ตัวแรกถูกกู้คืน หากint op stringได้รับการรักษาเป็นตัวอักษรมากกว่าการแสดงสตริงของมันจะถูกแทนที่ด้วย)^^|

โปรดทราบว่าในขณะที่สตริง (ซึ่งใน Golfscript ถูกเก็บไว้เป็นอาร์เรย์ของ int) จะแสดงค่าของตัวละครแต่ละตัว mod 256ค่าของตัวละครแต่ละตัวอาจอยู่นอกช่วงนี้ เมื่อทำการทดสอบความเป็นเอกลักษณ์ (ผ่านการตั้งค่าการทำงาน) หรือการมีอยู่ (ผ่าน?) มันเป็นค่าจริงที่ถูกเปรียบเทียบมากกว่าค่าการแสดงผล

ไฟล์ปะสำหรับล่าม Golfscript ปัจจุบัน :

61c61
<       to_gs
---
>       Gstring.new([self])

ดังกล่าวข้างต้นจะส่งผลกระทบต่อพฤติกรรมของstring op int(และในทางกลับกัน) ซึ่งเป็นหนึ่งในop ทุกสิ่งทุกอย่างยังคงได้รับผลกระทบรวมทั้งลักษณะการทำงานของ
+-|&^Gint`

โซลูชัน24 ไบต์ต่อไปนี้จะใช้งานได้:

{:i.)+.n*{*i%.}%i>|,}:f;

และสิ่งนี้ยังช่วยแก้ไขปัญหาที่น่าเกลียดอื่น ๆ อีกมากมาย


Python - 48 ไบต์

f=lambda n:len(set(10**-~i%n for i in range(n)))

ไม่ใช่ทางออกที่มีประสิทธิภาพมากที่สุด แต่ที่เหมาะสมสำหรับค่าที่น้อยกว่า100000

FWIW องค์ประกอบหลักเป็นเหมือนการแก้ปัญหาของฉันสำหรับการสร้างจำนวนวัฏจักรในทศนิยม

รุ่นเดียวกันที่มีประสิทธิภาพมากขึ้นของรหัสเดียวกัน ( 70 ไบต์ ):

 def f(n):
  a=[];i=10%n
  while i not in a:a+=i,;i=i*10%n
  return len(a)

ค่า99991ใช้เวลาน้อยกว่าหนึ่งวินาที


@PeterTaylor orเป็นอาร์เรย์ไปยังสตริงว่าง เนื่องจากเป็นการดำเนินการที่ชาญฉลาดรายการที่ซ้ำกันทั้งหมดจะถูกลบออกล่วงหน้า
โม่

แต่สตริงว่างมาจากไหน ถ้าฟังก์ชั่นนั้นมีในตัวเองฉันคิดว่าคุณจะต้องใช้ไบต์เพิ่มและสร้างมัน.|ขึ้นมา
ปีเตอร์เทย์เลอร์

1
@PeterTaylor แก้ไขแล้ว
primo

1
การเปลี่ยนแปลงพฤติกรรมของstring int +จะทำลายจำนวนมากของโปรแกรม ฉันไม่แน่ใจว่าจะใช้ ops อื่น ๆ ในคู่ของประเภทนั้นบ่อยแค่ไหน
Peter Taylor

@PeterTaylor ฉันเห็นด้วยมันจะ แต่พิจารณา: แปลง int เพื่อถ่าน: VS[]+''+ ''+ผนวก int เป็นถ่านเพื่อสตริง: VS[]++ +Apend int, เป็นตัวแทนสตริงสตริง: VS+ `+ในการใช้งานในปัจจุบันint''+มีความหมายเหมือนกันint`ซึ่งดูเหมือนว่าสิ้นเปลืองเมื่อพิจารณาความละเอียดของการบีบบังคับอาร์เรย์
primo

3

GolfScript, 48 47 46

ขอบคุณ @PeterTaylor ที่ตัดออกสองตัวอักษร

{2{1$1$%!{.@\/\d}*}:d~;5d;9{2$%}{10*9+}/+,}:f;

ฉันลองใช้ J แต่มันให้ผลแปลก ๆ กับฉันทุกครั้ง

ทดสอบออนไลน์

สิ่งนี้โดยทั่วไปจะแบ่ง 2 และ 5 ออกจากจำนวน (2 และ 5 เป็นปัจจัยสำคัญของ 10 และส่วนกลับของพวกเขาสิ้นสุดลงและสิ่งที่อัลกอริทึม) แล้วจำนวนเต็มต่ำที่สุด n ที่จำนวนผลลัพธ์ที่หาร 10 ^ n - 1 คือ ระยะเวลา


3
หากคุณรู้ว่าจะเรียกสายแรกไปยังฟังก์ชั่นของคุณคุณสามารถอินไลน์นิยามได้ เช่น{...}:d;...dคุณประหยัดได้ 1 char ด้วย...{...}:d~
Peter Taylor

@PeterTaylor ขอบคุณไม่เคยคิดมาก่อน
ความผันผวน

1
เมื่อได้แสดงความคิดเห็นกับเบ็นเกี่ยวกับการไม่ทิ้งfกองไว้ฉันสังเกตเห็นว่าคุณกำลังทำเช่นกัน คุณควรเพิ่ม a ;เพื่อป๊อปอัพฟังก์ชั่นเพื่อเปรียบเทียบอย่างเป็นธรรมกับภาษาอื่น ๆ
Peter Taylor

2
อีกไมโครเพิ่มประสิทธิภาพ: สามารถลงไปint array ,)\; int array +,
Peter Taylor

2

Perl, 52 ตัวอักษร

sub f{($p,%r)=1;1until$r{$p=$p*10%$_[0]}++;~~keys%r}

นี่คือการดำเนินการที่ไม่ซับซ้อนของวิธีการโดยตรง (โชคดีที่วิธีการโดยตรงนั้นค่อนข้างมีประสิทธิภาพ: ด้วยโมดูโลคณิตศาสตร์การคำนวณไม่เคยมีจำนวนมากกว่า 10 เท่าของค่าอินพุต)

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


ลองใช้อินพุต20ที่ให้ผลลัพธ์ที่ผิด
Howard

2

Clojure, 102, 117, 115, 106

unformated:

(defn r([n](r{}(iterate #(mod(* % 10)n)10)0))([a[f & s]i](if(a f)(- i(a f))(recur(assoc a f i)s(inc i)))))

จัดรูปแบบ:

(defn r
  ([n] (r {} (iterate #(mod (* % 10) n) 10) 0))
  ([a [f & s] i]
    (if (a f)
      (- i (a f))
      (recur
        (assoc a f i)
        s
        (inc i)))))

เวลาทำงานปรับตามระยะเวลา เกือบจะทันทีบนคอมพิวเตอร์ของฉันสำหรับค่าตัวอย่าง

โดยทั่วไปสิ่งนี้จะคำนวณผลลัพธ์ของการลบหลังจากแต่ละขั้นตอนในการหารแบบยาว ตรวจพบรอบหากจุดใดหมายเลขนั้นเหมือนกันกับจำนวนที่คำนวณไว้ก่อนหน้า


20แบ่งรหัสด้วยการป้อนข้อมูล คุณช่วยยืนยันได้ไหม
Howard

คุณพูดถูก จะดูว่าฉันสามารถแก้ไขได้
RedDeckWins

ผลลัพธ์ที่คาดหวังสำหรับ 20 คืออะไร
RedDeckWins

คำตอบที่ถูกต้องคือ 1
โฮเวิร์ด

น่าจะดีนะอัลกอริธึมแรกจะล้มเหลวในอินพุทมากมายเช่น 12 และ 20
RedDeckWins

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