Số shotgun


45

Các số Shotgun là một chuỗi với định nghĩa khá đơn giản nhưng một số cấu trúc thú vị. Bắt đầu với các số tự nhiên:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

Bây giờ lấy tất cả các số tại các chỉ số chia hết cho 2 , nhóm chúng thành các cặp và hoán đổi các số trong mỗi cặp:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...
   ^     ^     ^     ^      ^       ^       ^  
    <--->       <--->        <----->         <----
1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...

Bây giờ làm tương tự với các chỉ số chia hết cho 3 :

1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...
      ^        ^        ^           ^          
       <------>          <--------->           
1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...

Và sau đó cho 4 , 5 , 6 , v.v.

1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...
1, 4, 8, 6, 5, 3, 7, 2, 10, 12, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 3, 7, 2, 10, 5, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 14, 7, 2, 10, 5, 11, 3, 13, 16, ...
...

Sau k bước như vậy, các số k + 1 đầu tiên sẽ được cố định. Vì vậy, chúng ta có thể định nghĩa chuỗi vô hạn của số Shotgun là giới hạn cho phép k đi đến vô cùng. 66 số đầu tiên là:

1, 4, 8, 6, 12, 14, 16, 9, 18, 20, 24, 26, 28, 22, 39, 15, 36, 35, 40, 38, 57, 34, 48, 49, 51, 44,
46, 33, 60, 77, 64, 32, 75, 56, 81, 68, 76, 58, 100, 55, 84, 111, 88, 62, 125, 70, 96, 91, 98, 95,
134, 72, 108, 82, 141, 80, 140, 92, 120, 156, 124, 94, 121, 52, 152, 145, ...

Sự thật thú vị: Mặc dù có được chỉ bằng cách hoán vị các số tự nhiên, chuỗi này không chứa bất kỳ số nguyên tố nào.

Các thách thức

Cho một số nguyên n > 0, tìm nsố Shotgun thứ. Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN (hoặc thay thế gần nhất), đối số dòng lệnh hoặc đối số hàm và trả lại đầu ra hoặc in ra STDOUT (hoặc thay thế gần nhất).

Đây là mã golf, vì vậy bài nộp ngắn nhất (tính bằng byte) sẽ thắng.

Bảng xếp hạng

Điều này nhận được nhiều câu trả lời hơn tôi nghĩ, cũng như một số người cạnh tranh trong cùng một ngôn ngữ. Vì vậy, đây là một Snippet Stack để tạo cả bảng xếp hạng thông thường và tổng quan về người chiến thắng theo ngôn ngữ.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
Sự thật thú vị đó thật điên rồ, thuật toán này xáo trộn tất cả các số nguyên tố đến cùng? Hoặc có những số tự nhiên khác cũng sẽ không xảy ra?
Devon Parsons

1
@DevonParsons Có, nó xáo trộn tất cả các số nguyên tố "đến cùng". Nhưng tôi nghĩ có những con số khác bị mất là tốt. Dường như 10, 21, 2530không xuất hiện một trong hai, ví dụ.
Martin Ender

3
Điều này nghe có vẻ như một câu hỏi Project Euler. Tôi không nghĩ đó là ... nhưng có lẽ nó nên như vậy.
Corey Ogburn

9
Nói chung, ở klần lặp thứ, kphần tử thứ trong mảng được chuyển sang 2kvị trí thứ và sẽ không được chạm lại cho đến khi 2klặp lại, tại thời điểm đó, nó được chuyển sang 4kvị trí thứ, ad infinitum. Một nguyên tố không được chuyển đổi cho đến khi đến lượt của nó, có thể nói, vì vậy tất cả các số nguyên tố được xáo trộn về phía trước. Nhưng chúng ta có thể dễ dàng lập danh sách các nạn nhân vô tội chỉ bằng cách in ra phần tử đầu tiên được hoán vị ở lần lặp 2 và mỗi lần lặp lẻ. Danh sách đi: 2, 3, 5, 7, 10, 11, 13, 21, 17, 19, 30, 23, 27, 25, 29, 31, 45, 42, 37, 54, 41, 43, 65, ...
Théophile

3
@ Sherlock9 Xong! Nếu được chấp thuận, nó sẽ là https://oeis.org/A266679 . Chúc mừng năm mới!
Théophile

Câu trả lời:


5

Bình thường, 19 22

u-G*H^_!%GH/GHrhQ2Q

Một triển khai khá ngây thơ của câu trả lời golf của @ PeterTaylor .

Dùng thử trực tuyến tại đây

Điều này sử dụng các thủ thuật tương tự để chuyển đổi một vòng lặp while thành một nếp gấp như chương trình Pyth khác bên dưới.


u+G**H!%GHty%/GH2rhQ2Q

Một bản sao ngây thơ của thuật toán @ Sp3000 được dịch sang Pyth.

Bạn có thể thử trực tuyến tại đây

Sử dụng giảm (tên python cho nếp gấp) để mô phỏng vòng lặp while. Nó liệt kê những range(input, 2)gì trong Pyth làm việc ra range(2, input)[::-1]. Các sân golf khác liên quan đến Pyth liên quan đến việc sử dụng notthay vì <2và sử dụng ychế độ ẩn của nhân đôi giá trị của các đối số số.


21

> <>, 52 45 byte

Trang Esolang cho> <>

i:&&:&1-?vn;
2*1-*+20.>:&:&%1(&:&*{:}&:1-&,2%

Có rất nhiều yếu tố sao chép và di chuyển xung quanh, nhờ vào một số phép đo và phép nhân cần thiết. Logic hoàn toàn giống với giải pháp Python của tôi .

Lấy đầu vào thông qua một điểm mã từ STDIN, ví dụ "!" = 33 -> 75.


10
Và bạn đã nhận được giải thưởng cho định dạng đầu vào khó xử nhất từ ​​trước đến nay: P
Caridorc

Dù sao, đừng lo lắng :)
Caridorc

@ Sp3000 IMO, nó chỉ nên được tính là một
SuperJedi224

@ SuperJedi224 Trên thực tế, theo bài đăng meta này dường như -vđược tính là ba: /
Sp3000

17

Python 2, 58 byte

i=n=input()
while~-i:n+=(n%i<1)*i*(n/i%2*2-1);i-=1
print n

Giống như hầu hết các câu trả lời khác, ý tưởng là làm việc ngược lại.


Hãy gọi bước từng k+1bước i, để trên bước itất cả các bội số iđược hoán đổi. Chúng ta cần hai quan sát đơn giản:

  • Vị trí ntrong mảng chỉ được hoán đổi ở bước inếu nchia hết cho i,
  • Để biết bạn là số thấp hơn hay số cao hơn trong trao đổi, hãy nhìn vào n/i mod 2. Nếu đây là 1 bạn là số thấp hơn (và sẽ trao đổi lên), nếu không, bạn là số cao hơn (và sẽ hoán đổi xuống).

Điều này cho chúng ta một thuật toán để làm việc ngược. Hãy thử với 6, bắt đầu từ bước cuối cùng (bước i = 6):

Step 6: Position 6 swaps with position 12 (6 is divisible by 6, 6/6 = 1 == 1 mod 2)

Vì vậy, bây giờ chúng ta biết số đến từ vị trí 12. Sau đó:

Step 5: No swap (12 not divisible by 5)
Step 4: Position 12 swaps with position 16 (12 is divisible by 4, 12/4 = 3 == 1 mod 2)

Vì vậy, bây giờ chúng tôi biết nó đến từ 16 trước đó. Cuối cùng:

Step 3: No swap (16 not divisible by 3)
Step 2: Position 16 swaps with position 14 (16 divisible by 2, 16/2 = 8 == 0 mod 2)

Vì đây là bước đầu tiên (hãy nhớ, k+1), chúng tôi đã hoàn thành và số kết thúc ở vị trí 6 ban đầu đến từ vị trí 14, tức là số súng ngắn thứ 6 là 14.

Vì vậy, bây giờ cho lời giải thích Python:

i=n=input()             Read input, and store into i (step) and n (position)
while~-i:               while i-1 != 0:, or since we're descending with i this is just while i>1:
  n+=                   Add to the current position...
    (n%i<1)*            1* whatever's next if n is divisible by i, otherwise 0* (i.e. nothing)
    i*                  How many positions n might go up/down
    (n/i%2*2-1)         n/i%2 tell us higher/lower, *2-1 maps 0 or 1 to -1 (down) or +1 (up)
  i-=1                  Decrement the step number
print n                 Output

cách thú vị để viết i-1như~-i
mbomb007

6
@ mbomb007: Đồng ý. Khéo léo, vì nó có cùng ý nghĩa nhưng loại bỏ sự cần thiết cho một không gian sau while. Làm tốt lắm, Sp3000.
Alex A.

Ngắn nhất tôi có thể có được điều này trong pyth bằng cách sử dụng giảm:u+G**H!%GHty%/GH2rhQ2Q
FryAmTheEggman

1
@FryAmTheEggman, Sp3000, không ai trong số bạn sẽ đăng bài đó?
Martin Ender

@ MartinBüttner Ban đầu tôi không đăng nó vì tôi cảm thấy nó quá nhiều bản sao. Bây giờ tôi sẽ đăng nó dưới dạng câu trả lời CW.
FryAmTheEggman 11/03/2015

6

Haskell, 68 byte

n#k|mod k(2*n)<1=k-n|mod k n<1=k+n|k>0=k
s n=foldr((.).(#))id[2..n]n

Có lẽ là chơi gôn hơn nữa, đặc biệt là hàng đầu tiên. Điều này xác định một chức năng slấy nvà trả về nsố shotgun thứ.

map s [1..66]
[1,4,8,6,12,14,16,9,18,20,24,26,28,22,39,15,36,35,40,38,57,34,48,49,51,44,46,33,60,77,64,32,75,56,81,68,76,58,100,55,84,111,88,62,125,70,96,91,98,95,134,72,108,82,141,80,140,92,120,156,124,94,121,52,152,145]

Giải trình

Hàm trợ giúp #có hai số nktrả về ksố thứ tự trong danh sách được xác định bằng cách áp dụng thao tác hoán đổi cặp cho mỗi nsố thứ. Ví dụ: áp dụng nó cho 20 số đầu tiên n = 4mang lại kết quả này:

map (4#) [1..20]
[1,2,3,8,5,6,7,4,9,10,11,16,13,14,15,12,17,18,19,24]

Kết quả s nthu được bằng cách giảm ("gấp") danh sách [2..n]theo hàm bậc hai (.).(#), lấy một số mvà hàm f(ban đầu là hàm nhận dạng id) và trả về một hàm nhận kvà trả về f (m # k). Ví dụ, trong trường hợp n = 4danh sách [2,3,4]được giảm xuống thành một hàm nhận kvà trả về id (4 # (3 # (2 # k))). Điều idnày chỉ cần thiết cho trường hợp cơ sở n = 1, trong đó danh sách trống. Cuối cùng, chúng tôi cung cấp cho chức năng này đầu vào k = n, có được nsố shotgun thứ.



5

Ruby, 92 byte

def s(d,n)
d==1?n:s(d-1,n%d==0?n+(n%(d*2)==0?-d :d):n)
end
n=ARGV[0].to_i
print s(n,n).to_s

Nỗ lực chơi mã đầu tiên của tôi. Không dựa trên bất kỳ câu trả lời khác.


Bây giờ tôi đã xem xét một số khác, tôi nhận thấy rằng hầu hết chỉ xác định một chức năng, không phải là một chương trình hoàn chỉnh chấp nhận đầu vào và tạo đầu ra. OP yêu cầu một chương trình hoàn chỉnh với đầu vào và đầu ra. Có thông thường để bỏ qua các yêu cầu như vậy?


84 byte

n=ARGV[0].to_i
d=n
while d>1
n+=(n%d==0?(n%(d*2)==0?-d :d):0)
d-=1
end
print n.to_s

Sau khi xem xét các câu trả lời khác và nhận ra rằng một giải pháp lặp lại là có thể.


2
Một vài cải tiến cho giải pháp 84 byte của bạn: 1. Thay đổi ARGVthành $*ma thuật toàn cầu. 2. Điều to_skhông cần thiết. 3. Thay vì gán dcho nmột dòng riêng biệt, chỉ cần làm d=n=...để cạo một ký tự. Làm việc tốt cho golf đầu tiên của bạn! :)
Doorknob

1
Tôi đang yêu cầu một chương trình hoàn chỉnh ở đâu? "Bạn có thể viết một chương trình hoặc chức năng ...";) (Đây cũng là mặc định cho các thử thách chơi gôn mã , nhưng tôi thường bao gồm nó để hoàn thiện.)
Martin Ender

Để thêm vào các đề xuất của @ Doorknob, hai bộ dấu ngoặc trên n+=dòng là không cần thiết và cả hai lần xuất hiện đều ==0có thể được thay đổi thành an toàn <1.
Peter Taylor

5

Python 2, 97 79 ký tự

g=lambda n,k:n>1and g(n-1,k-(k%n<1)*n*(-1)**(k/n%2))or k
n=input()
print g(n,n)

Nó xác định cho mỗi chỉ số giá trị chính xác bằng cách theo đuổi đệ quy số lùi. Thuật toán được phát hiện độc lập.

chỉnh sửa: Bây giờ nó chỉ in nsố thứ thay vì số đầu tiên n. Tất nhiên cách tiếp cận lặp lại sẽ ngắn hơn, nhưng tôi không muốn sao chép mã của Sp3000.


Vâng, tôi nghĩ mọi người sẽ hội tụ về điều này. Tôi đã tìm thấy g(i,i)phần đặc biệt khó chịu mặc dù ...
Sp3000

2
Ngôn ngữ nên được đánh dấu là Python 2, vì printcâu lệnh.
mbomb007

@ mbomb007 Đã sửa nó.
Jakube

4

Haskell, 79 byte

1#i=i
s#i|i`mod`(2*s)==0=(s-1)#(i-s)|i`mod`s==0=(s-1)#(i+s)|1<2=(s-1)#i
p n=n#n

Cách sử dụng: p 66đầu ra nào145

Không có nhiều điều để giải thích: Hàm #tính toán đệ quy số shotgun ở vị trí ibước s. p ntrả về số ở vị trí ncủa bước n.


Ồ, tôi đã không thấy câu trả lời của bạn trước khi gửi của tôi. Có vẻ như chúng ta có cách tiếp cận khá khác nhau.
Zgarb

4

k, 41 byte

{{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}

 / apply to an int
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]} 42
111
 / apply to 1 through 66
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}'1+!66
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44 46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95 134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145
  • {...} lambda, x và y là đối số ngầm 1 và 2
  • $[b;t;f] toán tử ternary, đánh giá b theo sau là t / f tương ứng
  • b!a một modulo b
  • _ sàn, kết quả của sự phân chia thành một int
  • % bộ phận
  • {...}/[x;y] nguyên tố {...} với x và áp dụng trên danh sách y, tương đương với f [f [.. f [f [x; y0]; y1]; .. yn-1]; yn]
  • | đảo ngược
  • ! Hàm iota, tạo danh sách 0 đến n-1

4

Lisp thường gặp, 113 91

(lặp lại: 91)

(defun s(n)(do((r n(1- r)))((= r 1)n)(if(= 0(mod n r))(incf n(* r(if(oddp(/ n r))1 -1))))))

(bản gốc, đệ quy: 113)

(defun s(n &optional(r n))(cond((= r 1)n)((= 0(mod n r))(s(+ n(* r(if(oddp(/ n r))1 -1)))(1- r)))(t(s n(1- r)))))

Thí dụ

Với phiên bản đệ quy:

(trace s)
(s 10)

  0: (S 10)
    1: (S 20 9)
      2: (S 20 8)
        3: (S 20 7)
          4: (S 20 6)
            5: (S 20 5)
              6: (S 15 4)
                7: (S 15 3)
                  8: (S 18 2)
                    9: (S 20 1)
                    9: S returned 20
         ...
    1: S returned 20
  0: S returned 20

Xét nghiệm

Kiểm tra và biện pháp cho phiên bản lặp:

(let ((list '(1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44
              46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95
              134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145)))
  (time
   (loop for r in list
         for n from 1
         always (= r (s n)))))

 => T

Evaluation took:
  0.000 seconds of real time
  0.000000 seconds of total run time (0.000000 user, 0.000000 system)
  100.00% CPU
  807,160 processor cycles
  32,768 bytes consed

4

Toán học, 53 49 byte

(For[i=n=#,n>1,--n,If[n∣i,i+=Mod[i,2n]2-n]];i)&

Tôi quyết định đánh golf thực hiện tham khảo của tôi. Các là biểu tượng Unicode cho "phân chia", và tính cho 3 byte. Mặt khác, điều này sử dụng thuật toán tương tự như mọi người khác.

Nó định nghĩa một hàm không tên, lấy nmột tham số duy nhất và trả về nsố Shotgun thứ.


4

GolfScript, 27 ký tự

~.,(~%{):i\.@%!~)1$i/?i*-}/

Giải trình

Nếu f(i, n)là giá trị tại vị trí nsau khi i-1biến đổi, chúng ta có

f(1, n) = n
f(i, n) = f(i - 1, n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n)  for i > 1

trong đó ^biểu thị bitwise xor; đầu vào đã cho n, chúng tôi muốn tính toán f(n, n).

Việc chuyển đổi từ hàm đệ quy sang vòng lặp là không thú vị; điều thú vị là cách mà

n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n

có thể được viết lại. Cách tiếp cận rõ ràng hơn là nói rằng nó phải

n + (n % i == 0 ? i : 0) * g(n / i)

đối với một số g. Rõ ràng gxen kẽ giữa 1-1, khi các vị trí trao đổi luân phiên lên xuống; kể từ khi g(1) = 1(vì 1hoán đổi đến 2), chúng ta có

n + (n % i == 0 ? i : 0) * -1**(1 + n / i)

trong đó **biểu thị lũy thừa. Khoản tiết kiệm cuối cùng đến từ việc viết lại này như

n - i * (n % i == 0 ? -1 : 0)**(n / i)

Mổ xẻ

~             # Evaluate input to get n
.,(~%{        # For n-1 downto 1...
  ):i         #   Let i be that value + 1, so for i = n downto 2...
  \.@%!       #   Find n % i == 0 ? 1 : 0
  ~)          #   Negate
  1$i/?       #   Raise to the power of n/i
  i*-         #   Multiply by i and subtract
}/

Nhìn thấy khi bạn có câu trả lời ngắn nhất của GS và CJam, tại sao không có câu trả lời Pyth ngắn nhất? u-G*H^_!%GH/GHrhQ2QNếu bạn không muốn tự đăng bài này, hãy cho tôi biết / thêm nó vào câu trả lời của CW.
FryAmTheEggman

@FryAmTheEggman, tôi có thể không được thực hành nhiều ở CJam, nhưng ít nhất tôi có thể ít nhiều đọc nó. Tôi không biết những gì Pyth trong bình luận của bạn nói, mặc dù từ ngữ cảnh tôi cho rằng đó là một cổng của câu trả lời này. Vì vậy, tốt nhất là bạn đăng nó, bởi vì bạn có thể trả lời các câu hỏi về nó.
Peter Taylor


4

Julia, 61 57 byte

n->(i=n;while~-i!=0 n+=(n%i<1)*i*(n÷i%2*2-1);i-=1;end;n)

Điều này tạo ra một hàm không tên, lấy một đối số duy nhất nvà trả về nsố shotgun thứ. Để gọi nó, đặt tên cho nó, vd f=n->(...).

Ví dụ:

julia> for i = 1:10 println(f(i)) end
1
4
8
6
12
14
16
9
18
20

Hiện tại điều này dựa trên câu trả lời Python tuyệt vời của @ Sp3000 . Tôi sẽ xem lại điều này sớm vì phải có một cách ngắn hơn để làm điều này ở Julia so với những gì tôi đã làm ở đây. Bất kỳ đầu vào đều được chào đón, như mọi khi.



3

CJam, 28 27 byte

Vì vậy, điều này hơi xấu hổ ... trước khi đăng bài này, tôi đã thử chơi golf này và nhận được 30 byte trong CJam. Không có câu trả lời hiện có nào đánh bại điều đó. Trong khi đó, tôi cũng đã cạo được ba byte nữa. Có một giải pháp Pyth ngắn trong một chú thích, nhưng không ngắn hơn đã được đăng trong một câu trả lời, vì vậy ở đây nó được. Có lẽ nó truyền cảm hứng cho những người APL / J cố gắng hơn một chút (hoặc ai đó thực sự đăng giải pháp Pyth), trước khi tôi phải chấp nhận câu trả lời của riêng mình. ;)

l~__(,f-{_I_+%_+I-_zI=*+}fI

Kiểm tra nó ở đây.

Giải trình

l~                          "Read input N and eval.";
  __(,                      "Duplicate twice, create range [0 1 2 ... N-2].";
      f-                    "Subtract each from N, giving [N N-1 N-2 ... 2].";
        {               }fI "For each element, storing the element in I.";
         _I_+%_+I-          "Compute 2(N % 2I)-I - the shuffling offset";
                  _zI=      "Check that this offset is ±I.";
                      *+    "Multiply the offset by this boolean and update to N.";

3

J, 34 32 byte

   (]+[*(1-~2*2|%~)*0=|)/@(_1}2+i.)

   ((]+[*(1-~2*2|%~)*0=|)/@(_1}2+i.)) every 1+i.20  NB. running with inputs 1..20
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38

Sẽ cố gắng đánh gôn thêm một chút và thêm một số giải thích sau.

Hãy thử trực tuyến tại đây.



1

Ruby, 57 47 byte

Đây thực chất là giải pháp Python của Sp3000 (với đề xuất của xnor ) được dịch sang Ruby. Tôi có thể có thể chơi golf ở một vài nơi.

->n{n.downto(2).map{|i|n+=i*(n/i%2-~-n/i%2)};n}
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.