Thực hiện quy tắc chia hết cho 7


25

Để kiểm tra xem một số thập phân có chia hết cho 7 hay không:

Xóa chữ số cuối cùng. Nhân nó với 2 và trừ đi những gì còn lại. Nếu kết quả chia hết cho 7, số ban đầu chia hết cho 7.

(cũng được mô tả ví dụ ở đây )

Quy tắc này là tốt để kiểm tra phân chia thủ công. Ví dụ:

Năm 2016 có chia hết cho 7 không?

Trừ 6*2từ năm 201; chúng ta nhận được 189. Đây có phải là chia hết cho 7 không? Để kiểm tra nó, hãy áp dụng quy tắc một lần nữa.

Trừ 9*2từ 18; ta được 0. Do đó, năm 2016 chia hết cho 7.

Trong thử thách này, bạn nên áp dụng quy tắc này cho đến khi trạng thái chia hết là rõ ràng , nghĩa là con số không lớn hơn 70 (tuy nhiên, xem bên dưới để biết chi tiết). Tạo một chức năng hoặc một chương trình đầy đủ.

Đầu vào : một số nguyên dương; mã của bạn phải hỗ trợ đầu vào lên tới 32767 (hỗ trợ các số nguyên chính xác tùy ý là phần thưởng; xem bên dưới).

Đầu ra : một số nguyên (có thể âm), không lớn hơn 70, đó là kết quả của việc áp dụng quy tắc chia hết cho 7 hoặc nhiều lần.

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

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

Trong đó hai kết quả đầu ra có thể được chỉ định, một trong hai kết quả là chính xác: kết quả thứ hai tương ứng với việc áp dụng quy tắc một lần nữa. Nghiêm cấm áp dụng quy tắc trên một số có một chữ số: nếu bạn xóa chữ số đó, không có gì (không phải 0).


Tiền thưởng : Nếu thuật toán của bạn

nơi nlà số chữ số thập phân:

Trừ 50% từ số byte của mã của bạn.

Tiền thưởng thực sự :

Ngoài ra, nếu thuật toán của bạn đọc đầu vào theo hướng bình thường, bắt đầu từ chữ số có ý nghĩa nhất, hãy trừ 50% một lần nữa - điểm của bạn là 25% số byte của bạn (có vẻ như có thể, nhưng tôi không chắc lắm).


1
@DenkerAffe Trả lại đầu vào là có thể chấp nhận được. Tôi đã cập nhật trường hợp thử nghiệm của đầu vào = 10 để phản ánh điều này; đó là ý tưởng từ đầu
anatolyg

4
Tôi sẽ không muốn sử dụng quy tắc đó 1000000000000000000001.
Neil

1
Nhưng nếu ngôn ngữ của bạn có long longs hoặc một số loại tương đương được xây dựng thì sao?
SuperJedi224

1
Điều tôi đã nói là, trong một số triển khai, đó là số nguyên 128 bit, đủ lớn cho trường hợp thử nghiệm cuối cùng đó.
SuperJedi224

7
-1. Không phải tất cả các ngôn ngữ đều hỗ trợ độ chính xác tùy ý.
Hồ tháng ba

Câu trả lời:


23

Golf, 27 22 byte

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

Bạn có thể sử dụng nó theo cách này:

1000f

Giải trình

{.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 byte được lưu nhờ Dennis!


1
Chào mừng bạn đến với Câu đố lập trình và Code Golf. Đây là một câu trả lời tốt, tuy nhiên bạn có thể cải thiện nó bằng cách thêm phân tích và giải thích mã, như các câu hỏi ở trên. Để trả lời nhận xét này, hãy nhập @wizzwizz4( @sau đó tên người dùng của tôi) vào đầu (hoặc bất cứ nơi nào trong) một nhận xét.
wizzwizz4

1
@ wizzwizz4 Tốt hơn? Tôi không chắc là tôi hiểu ý của bạn khi nói 'sự cố mã' (không phải người bản ngữ xin lỗi)
Dica

8
Tôi tin rằng "sự cố mã", ông có nghĩa là một lời giải thích, mà bạn đã thêm vào. Đây là một câu trả lời đầu tiên rất tốt đẹp thực sự. Chào mừng đến với trang web!
Alex A.

1
Bạn có thể viết lại {...}{}ifphần dưới dạng {...}*, sẽ chỉ áp dụng khối mã 0 của một lần, tùy thuộc vào giá trị được đẩy bởi >. Ngoài ra, chúng tôi được phép thực hiện thêm một lần lặp (vì vậy thay thế 70bằng 9lưu một byte) và tôi không nghĩ bạn cần phải bật khối ;.
Dennis

3
@Dica, đây là câu trả lời đầu tiên đủ tốt để nhận được hơn 12 lượt upvote cho một câu hỏi chỉ với 624 lượt xem và nhận được lời khen ngợi từ hai người điều hành. Nếu bạn tiếp tục, bạn sẽ sớm vượt qua Dennis!
wizzwizz4

13

Haskell, 35 byte

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

Ví dụ sử dụng: until(<71)(\n->div n 10-2*mod n 10) 36893488147419103232 -> 32.

Không có gì nhiều để giải thích, đó là một triển khai trực tiếp của thuật toán.


9

Thạch, 11 byte

d⁵Uḅ-2µ>9$¿

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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.

Và như mọi khi, Jelly chiến thắng. Dennis, cần bao nhiêu byte để thực hiện trình thông dịch thạch trong Jelly?
Bálint

6

Python 2, 38 byte

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

Hãy thử nó ở đây !

Phương pháp đệ quy đơn giản. In x nếu <70 nếu không áp dụng quy tắc chia hết và gọi chính nó với kết quả.


bạn không cần không gian sau)
Maltysen 14/2/2016

@Maltysen Đúng. Sao chép dán sai, cảm ơn cho gợi ý!
Denker

2
Nếu quá dài dòng. f=lambda x:x*(x<70)or f(x/10-x%10*2)
Seequ 14/2/2016

1
@Seeq Thủ thuật hay, cảm ơn! Điều này sẽ hoạt động trên lý thuyết, nhưng nó đạt đến độ sâu đệ quy tối đa với năm 2016 là đầu vào trong khi phiên bản của tôi thì không. Bất cứ ý tưởng tại sao?
Denker

À, đúng rồi, không xem xét điều đó. Thủ thuật này được coi x*(x<70) != 0là điều kiện cuối cùng. Nếu x được về 0 - giống như năm 2016 - điều kiện kết thúc không bao giờ xảy ra.
Seequ 14/2/2016

6

Bình thường, 13 byte

.W>H9-/ZTyeZQ

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Điều này sẽ in tất cả các câu trả lời thay thế.

Giải trình:

.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 byte

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

Đây là hàm đệ quy chấp nhận một số nguyên và trả về a BigInt. Nếu đầu vào là một số lượng lớn như trong ví dụ trước, Julia phân tích nó như một BigInt, vì vậy không cần chuyển đổi thủ công.

Cách tiếp cận chỉ là một triển khai đơn giản của thuật toán. Nó sẽ tạo ra các đầu ra thay thế. Lấy mô-đun khi chia cho 10 sẽ thu được chữ số cuối cùng và thương số từ phép chia số nguyên cho 10 mang lại mọi thứ trừ chữ số cuối cùng.

Đã lưu một byte nhờ Dennis!


Chúng tôi được phép thực hiện thêm một lần lặp, vì vậy thay thế 70 bằng 9lưu một byte.
Dennis

@Dennis Gọi tốt, cảm ơn!
Alex A.

4

Bình thường, 17 byte

L?<b70by-/bT*%bT2

Hãy thử nó ở đây!

Cách tiếp cận đệ quy tương tự như trong câu trả lời python của tôi . Xác định lambda yđược gọi như thế này : y12345.
Bộ đếm byte trong trình thông dịch trực tuyến hiển thị 19 byte vì tôi đã thêm lệnh gọi lambda vào nó, vì vậy bạn có thể thử nó bằng cách nhấn nút chạy.

Giải trình

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

Bạn có một lỗi đánh máy trong lời giải thích của bạn, 17 nên là 70: P
FryAmTheEggman

4

CJam - 19 byte

Phiên bản do-while:

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

Dùng thử trực tuyến hoặc Trong khi phiên bản # 1:

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

Dùng thử trực tuyến hoặc Trong khi phiên bản # 2:

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

Hãy thử trực tuyến .

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 byte

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;

Không chơi gôn

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 byte - 50% = 71,5 byte

O (1) không gian, O (n) thời gian, vượt qua một lầ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!)

Sử dụng như 0![6,1,0,2]để áp dụng quy tắc cho năm 2016, tức là chuyển cho nó một số ở dạng luồng với con số ít quan trọng nhất trước tiên. Theo cách này, nó sẽ vượt qua chữ số bằng chữ số, áp dụng quy tắc với độ phức tạp không gian O (1).

Mã không mã hóa ở đây:

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

Ý chính của cách thức hoạt động là nó thực hiện thuật toán trừ từng chữ số , nhưng lợi dụng thực tế là mỗi số bị trừ tối đa là 2 chữ số, và vì vậy chúng ta có thể trừ đi một lượng tùy ý trong số 1- hoặc-2 chữ số từ số chính (cũng như ăn các chữ số có nghĩa ít nhất).

Thuật toán trừ là O (1) và chỉ lưu trữ giá trị 'mượn' hiện tại. Tôi đã thay đổi điều này để thêm vào chữ số phụ (0 hoặc 1) và chúng tôi lưu ý rằng giá trị vay này bị giới hạn (trong phạm vi [-2,2] vì vậy chúng tôi chỉ cần 3 bit để lưu trữ này).

Các giá trị khác được lưu trong bộ nhớ là các biến tạm thời đại diện cho số có 2 chữ số hiện tại để thêm, một lần nhìn trước trong luồng và để áp dụng một bước của thuật toán trừ (nghĩa là phải lấy hai chữ số và giá trị mượn và trả về một chữ số và một giá trị vay mới).

Cuối cùng, cuối cùng, nó xử lý hai chữ số cuối cùng trong luồng để trả về một số có một chữ số thay vì danh sách các chữ số.

NB sevHàm trong phiên bản không được chỉnh sửa sẽ hoạt động trên một Integer, chuyển đổi nó thành dạng luồng đảo ngược.


Tôi dự định tiền thưởng sẽ là thứ tự chữ số bình thường. Nhưng tôi chưa bao giờ nói điều đó, vì vậy thật công bằng khi nhận được tiền thưởng cho thứ tự đảo ngược, mặc dù nó ít vui hơn. Dù sao, ngay cả thứ tự đảo ngược cũng khó hơn tôi nghĩ, vậy là đủ vui rồi!
anatolyg

@anatolyg: Cảm ơn! Tôi không chắc liệu có thể thực hiện một lần thực hiện O (1) đơn hàng bình thường hay không ... quy tắc phụ thuộc vào các số liệu ít quan trọng nhất, vì vậy về mặt lý thuyết, việc áp dụng trực tiếp quy tắc là không thể ngoại trừ theo thứ tự đảo ngược. Điều khác duy nhất tôi có thể nghĩ là bằng cách tìm một dạng tương đương về mặt toán học - ví dụ Mod[18 - Quotient[n, 10] - 2*n, 21] - 18 + Quotient[n, 10]hoạt động theo kinh nghiệm cho n trong khoảng từ 10 đến 99, nhưng càng phức tạp hơn thì càng có nhiều chữ số n ...
nitơ

Hmm tôi đã nghĩ về nó và dường như có thể có một cách bằng cách giữ 2 chữ số phía trước và áp dụng từng chữ số tiếp theo, nhưng nhân với (-2) ^ n để tính đến nó 'lọc qua' ... theo như tôi có thể nói mặc dù không có cách nào để làm cho công việc này mà không cần giữ tất cả các chữ số trong bộ nhớ và hy sinh O (1) 'Ness hoặc thậm chí o (n)' Ness ... tôi nghĩ rằng trật tự bình thường chắc chắn là không thể :(
nitơ

1
Tôi e rằng bạn phải đếm số byte ban đầu 0khi gọi !, ví dụ như một phần (0!)(+ một dòng mới), tức là +5 byte. Mặt khác, bạn có thể rút ngắn phần đầu tiên để tạo mẫu khớp !với p![d]=p![d,e]=. Ngoài ra, sử dụng mô hình bảo vệ thay vì let: p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f).
nimi

1
@nitrous: Oh tôi đề cập (0!)đến một dòng của riêng nó. (0!)là chức năng bạn đưa ra như câu trả lời của bạn. Điều 0này là bắt buộc, nhưng không liên quan gì đến đầu vào, vì vậy bạn không thể thuê ngoài nó cho người gọi. Tất nhiên bạn cũng có thể sử dụng f x=0!x, nhưng điều này lâu hơn.
nimi

3

GNU dc, 20 15 byte

[10~2*-d70<F]sF

Điều này xác định chức năng dc đầu tiên (bao giờ) của tôi , F. Nó nhận đầu vào trên đỉnh của ngăn xếp và để đầu ra của nó ở đầu ngăn xếp. Ví dụ sử dụng:

36893488147419103232
lFxp
32

2

Toán học, 47 44 byte

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

Phương pháp đệ quy đơn giản. Có lẽ có thể được chơi golf hơn nữa.


#0[{1,-2}.QuotientRemainder[#,10]]tiết kiệm một byte.
njpipe tổ chức

2

R, 43 byte

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

Giải trình:

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

Chạy mẫu:

> 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 byte

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

Thất bại với 36893488147419103232 và sử dụng ~~(1/10)cũng sẽ thất bại cho700168844221

Kiểm tra:

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>


Tôi nhận được hai Fail... 70 và 32
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Yea tôi đến, tôi vẫn tự hỏi tại sao ...
andlrc

Bởi vì loại số của JavaScript không xử lý trường hợp cuối cùng, ít nhất.
Conor O'Brien

1
f=n=>n>70?f((n-n%10*21)/10):nlà phiên bản ngắn hơn nhưng vẫn chỉ hoạt động tối đa 2**56.
Neil

@Neil xem câu trả lời của tôi cho độ chính xác tùy ý, và xin vui lòng chơi golf, đánh giá rất cao.
Patrick Roberts

1

Toán học, 33 byte

#//.a_/;a>70:>⌊a/10⌋-2a~Mod~10&

Trường hợp thử nghiệm

%[9999]
(* -3 *)

1

Perl 5, 47 46 byte

Phải sử dụng bigintcho trường hợp thử nghiệm cuối cùng. (Nó trả về 20 mà không có)

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

Không thực sự chắc chắn đó là một ứng cử viên cho phần thưởng, vì vậy tôi đã không tính đến nó. (Tôi nghĩ là có, nhưng tôi không thực sự quen với các khái niệm này)

Hãy thử nó ở đây!


1

ES6, 108 byte

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

Hoạt động cho 2²⁵⁷ và 1000000000000000000001, nhưng có thể sử dụng chơi gôn thêm.


@PatrickRoberts Rất tiếc, giám sát khi định dạng lại cho bài nộp.
Neil

1

JavaScript ES6, 140 142 byte

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

Đây là toán học chính xác tùy ý, thậm chí hoạt động trên trường hợp thử nghiệm lớn nhất.

Hàm này loại bỏ đệ quy chữ số cuối cùng khỏi chuỗi, sau đó trừ 2 * chữ số cuối cùng khỏi chuỗi số còn lại bằng cách tăng số lượng chữ số để áp dụng cho minuend cho đến khi chênh lệch là dương. Sau đó, nó nối sự khác biệt đó vào cuối chuỗi với 0s được đệm phù hợp và tự gọi đệ quy cho đến khi giá trị số của nó nhỏ hơn hoặc bằng 9.

  • Chơi golf 7 byte nhờ @Neil (vâng tôi biết tôi đã tăng 2 byte nhưng tôi đã sửa một vài lỗi khiến hàm bị đóng băng hoặc trả lại đầu ra sai trong một số trường hợp).

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


Đẹp, nhưng nó có thể không hoạt động 1000000000000000000001.
Neil

1
Hãy thử s.replace(/.$/,'-$&*2'). Tôi không có bất kỳ ý tưởng rõ ràng cho phần còn lại mặc dù xin lỗi.
Neil

1

C #, 111 104 byte

int d(int n){var s=""+n;return n<71?n:d(int.Parse(s.Remove(s.Length-1))-int.Parse(""+s[s.Length-1])*2);}

1

Brain-Flak , 368 360 byte

Hãy thử trực tuyến!

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

Giải trình

Để bắt đầu, tất cả các mã nằm trong một vòng lặp chạy cho đến khi đỉnh của ngăn xếp nhỏ hơn 0:

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

Bên trong vòng lặp, chúng tôi chạy chia hết cho bảy thuật toán:

Nhân đôi đỉnh của ngăn xếp

(({}))

Lấy mod 10 của đỉnh ngăn xếp (chữ số cuối)

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

Đây là một chút lộn xộn nhưng phần còn lại của thuật toán tôi có thể giải thích nó sau nhưng tôi hoàn toàn không nhớ nó hoạt động như thế nào:

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

1

C, 56 byte - 75% = 14

Mặc dù điều này không đưa ra con số chính xác như các trường hợp thử nghiệm, nhưng nó thỏa mãn tinh thần của câu hỏi (và có thể tranh luận nhiều hơn). Nó xác định chính xác bội số chính xác của 7 và đưa ra phần còn lại chính xác cho các số khác (vì nó không bao giờ sử dụng số âm).

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

Không có phép nhân hoặc chia trong thuật toán, chỉ có phép cộng và phép trừ và các chữ số được xử lý trong một lần chuyển từ trái sang phải. Nó hoạt động như sau, bắt đầu bằng 0 trong bộ tích lũy:

  1. Trừ 7 nếu cần, và một lần nữa nếu vẫn cần thiết
  2. Nhân tổng số chạy với ba và thêm chữ số tiếp theo

Bước "nhân với ba" được viết là n-=-n-nđể lưu một byte và để tránh toán tử nhân.

Khi chúng tôi kết thúc, chúng tôi không trừ bảy, vì vậy kết quả sẽ nằm trong phạm vi 0-24; nếu bạn muốn một mô-đun nghiêm ngặt (0-7), thay thế *cbằng *c||n>6trongfor điều kiện vòng lặp.

Nó đủ điều kiện nhận thưởng tăng cường, bởi vì nó

  • hỗ trợ số nguyên chính xác tùy ý
  • chỉ thực hiện một lần chuyền trên đầu vào, theo thứ tự từ trái sang phải
  • có độ phức tạp không gian O (1)
  • có độ phức tạp thời gian O (n).

Chương trình kiểm tra và kết quả

#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

Phiên bản thay thế

Đây là một trong đó đệ quy (bạn sẽ muốn kích hoạt tối ưu hóa trình biên dịch để thực hiện chuyển đổi cuộc gọi đuôi hoặc bạn có thể làm tràn ngăn xếp của mình; tôi đã sử dụng 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;}

Gọi nó với '0' là đối số thứ hai.

Cả hai phiên bản đều tính toán phần còn lại-modulo-bảy trong số 60.000 chữ số dưới 50 mili giây trên máy của tôi.


Cảm ơn tiền thưởng - nó tạo ra một sự thay đổi thực sự cho C để kết thúc quá cạnh tranh! Hiện tại chỉ bị đánh bại bởi Jelly (11) và Pyth (13). :-)
Toby Speight

1

PHP, 50 byte

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

sử dụng đầu ra thay thế; làm việc lên đếnPHP_INT_MAX


phiên bản chuỗi, hoạt động với mọi số (dương) (64 byte):

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

0

Java, 133 byte

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

Tôi ghét cách verbose Integer.parseIntlà. Ung dung:

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