ใช้กฎการหารหารด้วย 7


25

วิธีตรวจสอบว่าตัวเลขทศนิยมหารด้วย 7 ได้ไหม:

ลบตัวเลขสุดท้าย คูณด้วย 2 และลบออกจากสิ่งที่เหลืออยู่ หากผลลัพธ์ถูกหารด้วย 7 ตัวเลขเดิมจะหารด้วย 7

(อธิบายด้วยเช่นที่นี่ )

กฎนี้ดีสำหรับการตรวจสอบหารด้วยตนเอง ตัวอย่างเช่น:

2016 หารด้วย 7 หรือไม่

ลบ6*2ออกจาก 201; เราได้ 189. นี่หารด้วย 7 ได้ไหม? เพื่อตรวจสอบลองใช้กฎอีกครั้ง

ลบ9*2ออกจาก 18; เราได้ 0 ดังนั้น 2559 หารด้วย 7 ได้

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

อินพุต : จำนวนเต็มบวก รหัสของคุณควรรองรับอินพุตสูงสุด 32767 (สนับสนุนจำนวนเต็มความแม่นยำโดยพลการเป็นโบนัสดูด้านล่าง)

เอาท์พุท : จำนวนเต็ม (อาจเป็นลบ) ไม่เกิน 70 นั่นเป็นผลมาจากการใช้การหารหารด้วย 7 กฎศูนย์หรือมากกว่าครั้ง

กรณีทดสอบ:

Input                   Output      Alternative output

1                       1
10                      10          1
100                     10          1
13                      13          -5
42                      42          0
2016                    0
9                       9
99                      -9
9999                    -3
12345                   3
32767                   28          -14

---------- Values below are only relevant for the bonus

700168844221            70          7
36893488147419103232    32          -1
231584178474632390847141970017375815706539969331281128078915168015826259279872    8

เมื่อมีการระบุเอาต์พุตที่เป็นไปได้สองรายการผลลัพธ์จะถูกต้อง: รายการที่สองสอดคล้องกับการใช้กฎอีกครั้ง ห้ามมิให้ใช้กฎนี้กับตัวเลขหลักเดียว: หากคุณลบตัวเลขจะไม่มีสิ่งใดเหลืออยู่ (ไม่ใช่ 0)


โบนัส : หากอัลกอริทึมของคุณ

โดยที่nเป็นจำนวนทศนิยม:

ลบ 50% จากจำนวนไบต์ของรหัสของคุณ

โบนัสจริง :

นอกจากนี้หากอัลกอริทึมของคุณอ่านอินพุตในทิศทางปกติเริ่มต้นจากตัวเลขที่สำคัญที่สุดลบ 50% อีกครั้ง - คะแนนของคุณคือ 25% ของจำนวนไบต์ของคุณ (ดูเหมือนเป็นไปได้ แต่ฉันไม่แน่ใจอย่างแน่นอน)


1
@DenkerAffe การส่งคืนอินพุตตามที่เป็นที่ยอมรับ ฉันอัปเดตกรณีทดสอบของอินพุต = 10 เพื่อสะท้อนสิ่งนี้ นั่นคือความคิดตั้งแต่เริ่มต้น
anatolyg

4
ฉันไม่ต้องการใช้กฎ1000000000000000000001นั้น
Neil

1
แต่จะเกิดอะไรขึ้นถ้าภาษาของคุณมีชนิดภาษาlong longอื่นหรือเทียบเท่า
SuperJedi224

1
สิ่งที่ฉันพูดคือในบางการใช้งานมันเป็นจำนวนเต็ม 128 บิตซึ่งมากกว่าขนาดใหญ่พอสำหรับกรณีทดสอบครั้งสุดท้าย
SuperJedi224

7
-1 ไม่ใช่ทุกภาษาที่รองรับความแม่นยำโดยพลการ
March Ho

คำตอบ:


23

Golfscript, 27 22 ไบต์

{.9>{.10/\10%2*-f}*}:f

คุณสามารถใช้วิธีนี้:

1000f

คำอธิบาย

{.9>{.10/\10%2*-f}*}:f
{                  }:f    # Define block 'f' (similar to a function)
 .                        # Duplicate the first value of the stack
  9>{            }*       # If the value on top of the stack is greater than 9 then the block is executed
     .10/\10%2*-          # Same as nb/10 - (nb%10 * 2) with some stack manipulations '.' to duplicate the top of the stack and '\' to swap the the first and second element of the stack
                f         # Execute block 'f'

บันทึก 5 ไบต์ด้วย Dennis!


1
ยินดีต้อนรับสู่การเขียนโปรแกรมปริศนาและรหัสกอล์ฟ นี่เป็นคำตอบที่ดี แต่คุณสามารถปรับปรุงได้โดยการเพิ่มรหัสแยกย่อยและคำอธิบายเช่นคำถามข้างต้น หากต้องการตอบกลับความคิดเห็นนี้พิมพ์@wizzwizz4(ตามด้วย@ชื่อผู้ใช้ของฉัน) ที่จุดเริ่มต้นของ (หรือที่ใดก็ได้ใน) ความคิดเห็น
wizzwizz4

1
@ wizzwizz4 ดีกว่าไหม? ฉันไม่แน่ใจว่าฉันเข้าใจสิ่งที่คุณหมายถึงโดย 'รหัสผิดพลาด' (ไม่ใช่เจ้าของภาษาขออภัย)
Dica

8
ฉันเชื่อว่าด้วย "การวิเคราะห์รหัส" เขาหมายถึงคำอธิบายที่คุณเพิ่ม นี่เป็นคำตอบแรกที่ดีมากอย่างแน่นอน ยินดีต้อนรับสู่เว็บไซต์!
Alex A.

1
คุณสามารถเขียน{...}{}ifส่วนหนึ่งเป็นที่เพิ่งจะนำไปใช้เป็นศูนย์ป้องกันรหัสของหนึ่งครั้งขึ้นอยู่กับค่าที่ผลักดันโดย{...}* >นอกจากนี้เรายังได้รับอนุญาตให้ดำเนินการอย่างใดอย่างหนึ่งมากขึ้นซ้ำ (ดังนั้นแทนที่70ด้วย9ช่วยประหยัดไบต์) ;และผมไม่คิดว่าคุณจะต้องปรากฏบล็อกด้วย
เดนนิส

3
@Dica นี่เป็นคำตอบแรกที่ดีพอที่จะได้รับ upvotes มากกว่า 12+ สำหรับคำถามที่มีเพียง 624 วิวและได้รับคำชมจากผู้ดูแลสองคน หากคุณติดตามเรื่องนี้คุณจะทันเดนนิส!
wizzwizz4

13

Haskell, 35 ไบต์

until(<71)(\n->div n 10-2*mod n 10)

ตัวอย่างการใช้งาน: ->until(<71)(\n->div n 10-2*mod n 10) 3689348814741910323232

ไม่มีอะไรที่จะอธิบายได้มากนักมันเป็นการใช้อัลกอริทึมโดยตรง


9

เยลลี่ 11 ไบต์

d⁵Uḅ-2µ>9$¿

ลองออนไลน์!

มันทำงานอย่างไร

d⁵Uḅ-2µ>9$¿  Main link. Input: n

d⁵           Divmod; return [n : 10, n % 10].
  U          Upend; yield [n % 10, n : 10].
   ḅ-2       Convert from base -2 to integer, i.e., yield -2 × (n % 10) + (n : 10).

      µ      Push the previous chain as a link and begin a new, monadic chain.
          ¿  Apply the previous chain while...
       >9$     its return value is greater than 9.

และเช่นเคยวุ้นชนะ เดนนิสต้องใช้ไบต์เท่าใดในการใช้ล่ามเยลลี่ในเยลลี่
Bálint

6

Python 2, 38 ไบต์

f=lambda x:f(x/10-x%10*2)if x>70else x

ลองที่นี่ !

วิธีการเรียกซ้ำง่าย พิมพ์ x หาก <70 เป็นอย่างอื่นจะใช้กฎการหารและเรียกตัวเองกับผลลัพธ์


คุณไม่ต้องการช่องว่างหลังจาก)
Maltysen

@Maltysen True คัดลอกวางผิดคนขอบคุณสำหรับคำใบ้!
Denker

2
ถ้าเป็น verbose มากเกินไป f=lambda x:x*(x<70)or f(x/10-x%10*2)
seequ

1
@Seeq เคล็ดลับดีขอบคุณ! สิ่งนี้ควรใช้งานได้ในทางทฤษฎี แต่ถึงความลึกสูงสุดของการเรียกซ้ำด้วย 2016 เป็นอินพุตในขณะที่เวอร์ชันของฉันไม่ทำงาน มีความคิดอะไรบ้าง
Denker

อาใช่ไม่ได้คิดอย่างนั้น เคล็ดลับนี้ถือx*(x<70) != 0เป็นเงื่อนไขสิ้นสุด ถ้า x เท่ากับ 0 - เช่นเดียวกับปี 2016 - เงื่อนไขสิ้นสุดไม่เคยเกิดขึ้น
seequ

6

Pyth, 13 ไบต์

.W>H9-/ZTyeZQ

ลองออนไลน์: การสาธิตหรือชุดทดสอบ

นี่จะพิมพ์คำตอบอื่นทั้งหมด

คำอธิบาย:

.W>H9-/ZTyeZQ   
            Q   read a number from input
.W              while
  >H9              the number is greater than 9
                do the following with the number:
      /ZT          divide it by 10
     -             and subtract
         yeZ       2*(number%10)

5

Julia, 27 26 ไบต์

f(x)=x>9?f(x÷10-x%10*2):x

BigIntนี่คือฟังก์ชันเวียนที่ยอมรับเป็นจำนวนเต็มและผลตอบแทน หากอินพุตเป็นจำนวนมากเช่นในตัวอย่างสุดท้าย Julia จะแยกวิเคราะห์เป็น a BigIntดังนั้นไม่จำเป็นต้องทำการแปลงด้วยตนเอง

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

บันทึกเป็นไบต์ขอบคุณ Dennis!


เราอนุญาตให้ทำการวนซ้ำได้มากกว่าหนึ่งครั้งดังนั้นการแทนที่70ด้วยการ9บันทึกไบต์
เดนนิส

@Dennis โทรดีขอบคุณ!
Alex A.

4

Pyth, 17 ไบต์

L?<b70by-/bT*%bT2

ลองที่นี่!

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

คำอธิบาย

L?<b70by-/bT*%bT2

L                  # Defines the lambda y with the parameter b
 ?<b70             # if b < 70:
      b            # return b, else:
       -/bT*%bT2   # calculate b/10 - b%10*2 and return it

คุณพิมพ์ผิดในคำอธิบายของคุณ 17 ควรเป็น 70: P
FryAmTheEggman

4

CJam - 19 ไบต์

รุ่น Do-while:

r~A*{`)]:~~Y*-_9>}g

ลองใช้งานออนไลน์หรือในขณะที่เวอร์ชัน # 1:

r~{_9>}{`)]:~~Y*-}w

ลองใช้งานออนไลน์หรือในขณะที่เวอร์ชัน 2:

r~{_9>}{_A/\A%Y*-}w

ลองมันออนไลน์

r~                     | Read and convert input
  A*                   | Multiply by 10 to get around "if" rule
     `                 | Stringify
      )                | Split last character off
       ]               | Convert stack to array
        :~             | Foreach in array convert to value
          ~            | Dump array
           Y*          | Multiply by 2
             -         | Subtract
              _        | Duplicate
               9>      | Greater than 9?
    {            }g    | do-while

3

Oracle SQL 11.2, 116 ไบต์

WITH v(i)AS(SELECT:1 FROM DUAL UNION ALL SELECT TRUNC(i/10)-(i-TRUNC(i,-1))*2 FROM v WHERE i>70)SELECT MIN(i)FROM v;

ยกเลิกแข็งแรงเล่นกอล์ฟ

WITH v(i) AS
(
  SELECT :1 FROM DUAL
  UNION ALL
  SELECT TRUNC(i/10)-(i-TRUNC(i,-1))*2 FROM v WHERE i>70
)
SELECT MIN(i) FROM v;

3

Haskell, 157 192 184 167 159 147 138 + 5 ไบต์ - 50% = 71.5 ไบต์

O (1) สเปซ, เวลา O (n), ซิงเกิ้ลพาส!

h d=d%mod d 10
d%r=(quot(r-d)10,r)
p![d]=d-p*10
p![d,e]=d#(e-p)
p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f)
m#0=m
m#n=n-2*m
(0!)

ใช้0![6,1,0,2]เพื่อใช้กฎกับ 2016 คือส่งตัวเลขในรูปแบบสตรีมที่มีตัวเลขสำคัญน้อยที่สุดก่อน ด้วยวิธีนี้มันจะผ่านจำนวนตัวเลขหลักโดยใช้กฎที่มีความซับซ้อนของพื้นที่ O (1)

รหัส ungolfed อยู่ที่นี่:

import Data.Char

{- sub a b = sub2 0 a b
  where
    sub2 borrow (a:as) (b:bs) = res : sub2 borrow2 as bs
      where
        (borrow2, res) = subDig borrow a b
    sub2 borrow (a:as) [] = sub2 borrow (a:as) (0:[])
    sub2 _ [] _ = [] -}

--subDig :: Int -> Int -> Int -> (Int, Int)
subDig borrow a b = subDig2 (a - b - borrow)
  where
    subDig2 d = subDig3 d (d `mod` 10)
    subDig3 d r = ((r-d) `quot` 10, r)

seven ds = seven2 0 ds
seven2 borrow (d:e:f:gs) = seven2 (b + borrow2) (res:f:gs)
  where
    (a, b) = double d
    (borrow2, res) = subDig borrow e a
seven2 borrow (d:e:[]) = finalApp d (e-borrow)
seven2 borrow (d:[]) = d - borrow*10

double d = ((2*d) `mod` 10, (2*d) `quot` 10)

finalApp m 0 = m
finalApp m n = n - 2*m

num2stream :: Int -> [Int]
num2stream = reverse . map digitToInt . show
sev = seven . num2stream

ส่วนสำคัญของวิธีการทำงานนี้คือใช้อัลกอริธึมการลบแบบตัวเลขต่อหลักแต่ใช้ประโยชน์จากความจริงที่ว่าแต่ละหมายเลขที่จะถูกลบนั้นมีจำนวนมากที่สุด 2 หลักและเราสามารถลบจำนวน 1- เหล่านี้ตามอำเภอใจ หรือ - ตัวเลข 2 หลักจากหมายเลขหลัก

อัลกอริทึมการลบคือ O (1) และเก็บเฉพาะค่า 'ยืม' ปัจจุบัน ฉันเปลี่ยนสิ่งนี้เพื่อเพิ่มจำนวนหลักพิเศษ (ทั้ง 0 หรือ 1) และเราทราบว่ามูลค่ายืมนี้ถูกผูกไว้ (ภายในช่วง [-2,2] ดังนั้นเราจึงต้องการเพียง 3 บิตในการจัดเก็บนี้)

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

ในที่สุดตอนท้ายมันจะประมวลผลตัวเลขสองหลักสุดท้ายในกระแสพร้อมกันเพื่อส่งกลับตัวเลขหลักเดียวแทนที่จะเป็นรายการของตัวเลข

NB sevฟังก์ชั่นในเวอร์ชั่นที่ไม่ได้รับการดัดแปลงจะทำงานบนIntegerและแปลงเป็นรูปแบบการสตรีมแบบกลับด้าน


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

@anatolyg: ขอบคุณ! ฉันไม่แน่ใจว่าเป็นไปได้หรือไม่ที่จะใช้ O (1) ในการดำเนินการตามคำสั่งปกติเดียว ... กฎขึ้นอยู่กับตัวเลขที่มีนัยสำคัญน้อยที่สุดดังนั้นในทางทฤษฎีการประยุกต์โดยตรงของกฎนั้นเป็นไปไม่ได้ยกเว้นในลำดับย้อนกลับ สิ่งเดียวที่ฉันคิดได้ก็คือการหารูปแบบที่เทียบเท่าทางคณิตศาสตร์ - ตัวอย่างเช่นการMod[18 - Quotient[n, 10] - 2*n, 21] - 18 + Quotient[n, 10]ทำงานเชิงประจักษ์สำหรับ n ระหว่าง 10 และ 99 แต่ซับซ้อนยิ่งขึ้นยิ่งตัวเลข n มี ...
nitrous

อืมฉันคิดเกี่ยวกับมันและดูเหมือนว่าอาจจะมีวิธีหนึ่งโดยเก็บเลขสองหลักไว้ด้านหน้าและใช้แต่ละหลักถัดไป แต่คูณด้วย (-2) ^ n เพื่อพิจารณาว่า 'กรองผ่าน' ... เท่าที่ฉัน สามารถบอกได้ว่าไม่มีวิธีที่จะทำให้งานนี้โดยไม่ต้องรักษาตัวเลขทั้งหมดในความทรงจำและเสียสละของ O (1) 'ness หรือแม้แต่ o (n)' ness ... ฉันคิดว่าคำสั่งปกติเป็นไปไม่ได้แน่นอน :(
nitrous

1
ฉันเกรงว่าคุณจะต้องนับไบต์ของการเริ่มต้น0เมื่อมีการโทร!เช่นกันเป็นส่วน(0!)(+ ขึ้นบรรทัดใหม่) เช่น +5 ไบต์ ในด้านอื่น ๆ ที่คุณสามารถร่นแรกกับรูปแบบการแข่งขันของ!การและp![d]= p![d,e]=และใช้การ์ดรูปแบบแทนlet: p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f).
nimi

1
@nitrous: โอ้ฉัน(0!)พูดถึงมันเป็นของตัวเอง (0!)เป็นฟังก์ชั่นที่คุณให้เป็นคำตอบของคุณ 0ที่จำเป็น แต่มีอะไรจะทำอย่างไรกับการป้อนข้อมูลดังนั้นคุณจึงไม่สามารถ outsource มันไปยังผู้โทร แน่นอนคุณสามารถใช้งานf x=0!xได้ แต่จะนานกว่านี้
nimi

3

GNU dc, 20 15 ไบต์

[10~2*-d70<F]sF

สิ่งนี้นิยามฟังก์ชั่น dc (เคย) ครั้งแรกของฉัน, F. ใช้อินพุตที่ด้านบนสุดของสแต็กและปล่อยเอาต์พุตไว้ที่ด้านบนสุดของสแต็ก ตัวอย่างการใช้งาน:

36893488147419103232
lFxp
32

2

Mathematica, 47 44 ไบต์

If[#>70,#0[{1,-2}.{⌊#/10⌋,#~Mod~10}],#]&

วิธีการเรียกซ้ำง่าย อาจจะเล่นกอล์ฟต่อไป


#0[{1,-2}.QuotientRemainder[#,10]]บันทึกเป็นไบต์
njpipeorgan

2

R, 43 ไบต์

x=scan();while(x>70)x=floor(x/10)-x%%10*2;x

คำอธิบาย:

x=scan()                                      # Takes input as a double
        ;                                     # Next line
         while(x>70)                          # While-loop that runs as long x > 70
                      floor(x/10)             # Divide x by 10 and round that down
                                 -x%%10*2     # Substract twice the last integer
                    x=                        # Update x
                                         ;    # Next line once x <= 70
                                          x   # Print x

ตัวอย่างการวิ่ง:

> x=scan();while(x>70)x=floor(x/10)-x%%10*2;x
1: 9999
2: 
Read 1 item
[1] -3

> x=scan();while(x>70)x=floor(x/10)-x%%10*2;x
1: 32767
2: 
Read 1 item
[1] 28

1

JavaScript ES6, 38 ไบต์

a=i=>i>70?a(Math.floor(i/10)-i%10*2):i

การล้มเหลวด้วย36893488147419103232และการใช้~~(1/10)จะล้มเหลวด้วย700168844221

ทดสอบ:

a=i=>i>70?a(Math.floor(i/10)-i%10*2):i
O.textContent = O.textContent.replace(/(-?\d+) +(-?\d+)/g, (_,i,o) =>
  _+": "+(a(+i)==o?"OK":"Fail")
);
<pre id=O>1                       1
10                      10
100                     10
13                      13
42                      42
2016                    0
9                       9
99                      -9
9999                    -3
12345                   3
700168844221            70
36893488147419103232    32</pre>


ฉันได้รับสองFail... 70 และ 32
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴใช่ฉันยังฉันยังคงสงสัยว่าทำไม ...
andlrc

เนื่องจากประเภทหมายเลขของ JavaScript ไม่ได้รองรับตัวพิมพ์ใหญ่อย่างน้อย
Conor O'Brien

1
f=n=>n>70?f((n-n%10*21)/10):nเป็นรุ่นที่สั้นลง 2**56แต่ยังคงทำงานเฉพาะสำหรับการขึ้นไป
Neil

@ ไม่มีเห็นคำตอบของฉันสำหรับความแม่นยำโดยพลการและโปรดไปที่กอล์ฟชื่นชมอย่างมาก
Patrick Roberts เมื่อ


1

Perl 5, 47 46 ไบต์

ต้องใช้bigintสำหรับกรณีทดสอบครั้งสุดท้าย (มันคืนค่า 20 โดยไม่มี)

use bigint;$_=<>;while($_>9){$_-=2*chop;}print

ไม่แน่ใจจริงๆว่าเป็นผู้สมัครรับโบนัสดังนั้นฉันจึงไม่ได้คำนึงถึง (ฉันคิดว่ามันทำได้ แต่ฉันไม่คุ้นเคยกับแนวคิดจริงๆ)

ลองที่นี่!


1

ES6, 108 ไบต์

f=(s,n=0)=>s>1e9?f(s.slice(0,-1),((1+s.slice(-1)-n%10)%10*21+n-s.slice(-1))/10):s>9?f(((s-=n)-s%10*21)/10):s

ใช้งานได้สำหรับ2²⁵⁷และ 1000000000000000000001 แต่สามารถเล่นกอล์ฟต่อไปได้


@PatrickRoberts อ๊ะตรวจสอบเมื่อฟอร์แมตใหม่สำหรับการส่ง
Neil

1

JavaScript ES6, 140 142 ไบต์

f=s=>s>9?eval("t=s.replace(/.$/,'-$&*2');for(i=-1;0>(n=eval(u=t[c='slice'](i-4)))&&u!=t;i--);n<0?n:f(t[c](0,i-4)+('0'.repeat(-i)+n)[c](i))"):s

นี่คือคณิตศาสตร์ที่มีความแม่นยำตามอำเภอใจจริง ๆ แม้ใช้กับกรณีทดสอบที่ใหญ่ที่สุด

ฟังก์ชั่นนี้จะลบตัวเลขสุดท้ายออกจากสตริงซ้ำแล้วลบ 2 * ตัวเลขสุดท้ายจากสตริงตัวเลขที่เหลืออยู่โดยเพิ่มจำนวนหลักเพื่อนำไปใช้กับ minuend ซ้ำ ๆ จนกว่าความแตกต่างจะเป็นค่าบวก จากนั้นก็จะผนวกความแตกต่างกับจุดสิ้นสุดของสตริงที่มีเบาะเหมาะสมที่และเรียกตัวเองซ้ำจนกว่าค่าตัวเลขที่น้อยกว่าหรือเท่ากับ09

  • Golfed 7 ไบต์ขอบคุณ @Neil (ใช่ฉันรู้ว่าฉันได้รับ 2 ไบต์ แต่ฉันแก้ไขข้อผิดพลาดเล็กน้อยที่ทำให้ฟังก์ชันหยุดทำงานหรือส่งคืนเอาต์พุตผิดสำหรับบางกรณี)

f=s=>s>9?eval("t=s.replace(/.$/,'-$&*2');for(i=-1;0>(n=eval(u=t[c='slice'](i-4)))&&u!=t;i--);n<0?n:f(t[c](0,i-4)+('0'.repeat(-i)+n)[c](i))"):s;[['1',1],['10',1],['100',1],['13',-5],['42',0],['2016',0],['9',9],['99',-9],['9999',-3],['12345',3],['700168844221',7],['36893488147419103232',-1],['231584178474632390847141970017375815706539969331281128078915168015826259279872',8]].map(a=>document.write(`<pre>${f(a[0])==a[1]?'PASS':'FAIL'} ${a[0]}=>${a[1]}</pre>`))


ดี 1000000000000000000001แต่มันอาจจะไม่ทำงานใน
Neil

1
ลองs.replace(/.$/,'-$&*2')ดู ฉันไม่มีความคิดที่ชัดเจนสำหรับส่วนที่เหลือแม้ว่าจะเสียใจด้วย
Neil


1

Brain-Flak , 368 360 ไบต์

ลองออนไลน์!

([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>){{}(({}))(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>([([([(({}<{}><>)<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})]<(())>)(<>)]){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)}{}

คำอธิบาย

ในการเริ่มต้นโค้ดทั้งหมดที่อยู่ในลูปที่รันจนกระทั่งส่วนบนของสแต็กน้อยกว่าศูนย์:

([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)
{{}
 ...
 ([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)
}{}

ภายในวงเราเรียกใช้การหารด้วยอัลกอริทึมเจ็ด:

ทำซ้ำส่วนบนสุดของสแต็ก

(({}))

ใช้ mod 10 ของด้านบนของสแต็ค (หลักสุดท้าย)

(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>)

นี่เป็นระเบียบเล็กน้อย แต่ทำส่วนที่เหลือของอัลกอริทึมที่ฉันอาจอธิบายในภายหลัง แต่ฉันจำไม่ได้เลยว่ามันทำงานอย่างไร:

([(({})<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})

1

C, 56 ไบต์ - 75% = 14

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

n;f(char*c){for(n=0;*c;)n-=n>6?7:'0'-n-n-*c++;return n;}

ไม่มีการคูณหรือการหารในอัลกอริทึมการเพิ่มและการลบเท่านั้นและตัวเลขจะถูกประมวลผลในการส่งผ่านครั้งเดียวจากซ้ายไปขวา มันทำงานดังนี้เริ่มต้นด้วย 0 ในการสะสม:

  1. ลบ 7 หากจำเป็นและอีกครั้งหากจำเป็น
  2. คูณผลรวมสะสมสามและเพิ่มตัวเลขถัดไป

ขั้นตอน "คูณด้วยสาม" ถูกเขียนเป็น n-=-n-nเพื่อบันทึกไบต์และเพื่อหลีกเลี่ยงการดำเนินการคูณ

เมื่อเราถึงจุดสิ้นสุดเราจะไม่ลบ sevens ดังนั้นผลลัพธ์จะอยู่ในช่วง 0-24; ถ้าคุณต้องการโมดูลัสแบบเข้มงวด (0-7) ให้แทนที่*cด้วย*c||n>6ในforเงื่อนไขลูป

มันมีคุณสมบัติสำหรับโบนัสที่เพิ่มขึ้นเพราะมัน

  • รองรับจำนวนเต็มความแม่นยำโดยพลการ
  • ดำเนินการส่งผ่านเพียงครั้งเดียวในการป้อนข้อมูลในลำดับจากซ้ายไปขวา
  • มีความซับซ้อนของพื้นที่ O (1)
  • มีความซับซ้อนของเวลา O (n)

โปรแกรมทดสอบและผลลัพธ์

#include <stdio.h>
int main(int argc, char **argv) {
    while (*++argv)
        printf("%s -> %d\n", *argv, f(*argv));
    return 0;
}
540 -> 15
541 -> 16
542 -> 17
543 -> 18
544 -> 19
545 -> 20
546 -> 21
547 -> 22
548 -> 23
549 -> 24
550 -> 18
99 -> 15
999 -> 12
12345 -> 11
32767 -> 7
700168844221 -> 7
36893488147419103232 -> 11
231584178474632390847141970017375815706539969331281128078915168015826259279872 -> 11

รุ่นทางเลือก

นี่คือสิ่งที่เกิดขึ้นซ้ำ (คุณจะต้องเปิดใช้งานการเพิ่มประสิทธิภาพคอมไพเลอร์เพื่อทำการแปลงแบบหางเรียกหรือคุณอาจล้นสแต็กของคุณฉันใช้gcc -std=c89 -O3):

f(c,n)char*c;{return n>6?f(c,n-7):*c?f(c+1,n+n+n+*c-'0'):n;}

เรียกว่าด้วย '0' เป็นอาร์กิวเมนต์ที่สอง

ทั้งสองเวอร์ชันคำนวณส่วนที่เหลือ - โมดูโลเจ็ดของจำนวน 60,000 หลักในเวลาไม่เกิน 50 มิลลิวินาทีในเครื่องของฉัน


ขอบคุณสำหรับโบนัส - มันทำให้การเปลี่ยนแปลงที่แท้จริงสำหรับ C จบลงด้วยการแข่งขันที่รุนแรง! ขณะนี้แพ้โดยJelly (11) และPyth (13) เท่านั้น :-)
Toby Speight

1

PHP, 50 ไบต์

for($n=$argv[1];$n>9;)$n=$n/10|0-2*($n%10);echo$n;

ใช้เอาต์พุตทางเลือก ทำงานได้ถึงPHP_INT_MAX


รุ่นสตริงใช้งานได้กับจำนวนใด ๆ (บวก) (64 ไบต์):

for($n=$argv[1];$n>9;)$n=substr($n,0,-1)-2*substr($n,-1);echo$n;

0

Java, 133 ไบต์

int d(int n){String s=""+n;return n<71?n:d(Integer.parseInt(s.replaceFirst(".$",""))-Integer.parseInt(""+s.charAt(s.length()-1))*2);}

ฉันเกลียดวิธีการอย่างละเอียดInteger.parseIntคือ Ungolfed:

static int div(int n) {
    if (n <= 70) {
        return n;
    } else {
        String num = ("" + n);
        int last = Integer.parseInt("" + num.charAt(num.length() - 1));
        int k = Integer.parseInt(num.replaceFirst(".$", "")) - last * 2;
        return div(k);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.