11 = (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3) + (6) - (4)


35

Cho một số nguyên dương N , nhiệm vụ của bạn là trả về số bước cần thiết theo thuật toán sau để đạt N :

  1. Tìm số nhỏ hình tam giác T i như rằng T i  ≥ N . Xây dựng danh sách tương ứng L = [1, 2, ..., i] .

  2. Trong khi tổng các điều khoản của L lớn hơn N , hãy xóa thuật ngữ đầu tiên khỏi danh sách.

  3. Nếu tổng các điều khoản của L bây giờ nhỏ hơn N , hãy tăng i và nối nó vào danh sách. Tiếp tục với bước # 2.

Chúng tôi dừng lại ngay khi N đạt được. Chỉ bước đầu tiên được thực hiện một cách có hệ thống. Bước # 2 và # 3 có thể không được xử lý.

Ví dụ

Dưới đây là một ví dụ cho N = 11 :

Thí dụ

Vậy sản lượng dự kiến ​​cho N = 114 .

Những ví dụ khác:

  • N = 5 - Chúng tôi bắt đầu với T 3 = 1 + 2 + 3 = 6 , tiếp theo là 2 + 3 = 5 . Sản lượng dự kiến: 2 .
  • N = 10 - Chỉ yêu cầu bước đầu tiên vì 10 là số tam giác: T 4 = 1 + 2 + 3 + 4 = 10 . Sản lượng dự kiến: 1 .

100 giá trị đầu tiên

Dưới đây là kết quả cho 1 ≤ N 100 :

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

Quy tắc

  • Bạn có thể viết một chương trình đầy đủ hoặc một chức năng, in hoặc trả về kết quả.
  • Bạn được yêu cầu xử lý bất kỳ N ≤ 65536 nào trong vòng chưa đầy một phút trên phần cứng tầm trung.
  • Cho đủ thời gian, về mặt lý thuyết , chương trình / chức năng của bạn sẽ hoạt động với bất kỳ giá trị nào của N được hỗ trợ bởi ngôn ngữ của bạn. Nếu không, vui lòng giải thích lý do tại sao trong câu trả lời của bạn.
  • Đây là mã golf, vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng!

Liên quan. (Tôi nghi ngờ bạn đã biết về cái này, nhưng chỉ đăng nó cho hậu thế)
ETHproductions

Giá trị tối đa của N chúng ta cần xử lý là bao nhiêu?
Lu-ca

@Luke Vui lòng xem các quy tắc cập nhật.
Arnauld

Câu trả lời:


4

Thạch , 29 31 byte

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

Một liên kết đơn âm trả về kết quả (N = 65536 mất ít hơn hai giây).

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

Làm sao?

Để được giải thích kỹ lưỡng về thuật toán, hãy xem bài viết tuyệt vời của Martin Ender .

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

Việc thực hiện toàn bộ chương trình 29 byte mà tôi đã tạo bằng thuật toán được mô tả mất 4 phút 30 cho N = 65536 trên máy tính xách tay của tôi, vì vậy tôi cho rằng nó không được tính.

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

Sử dụng vòng lặp while cho mỗi bước 3 và sử dụng lại như bước 1 có độ dài bằng với những gì tôi có thể quản lý khi khởi tạo danh sách vì không kiểm tra bước 3 có nghĩa là xây dựng danh sách cho đến khi không còn gì và sau đó tìm chỉ mục đầu tiên của giá trị:

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i

25

Toán học, 79 byte

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&

Giải trình

Tôi không thể bận tâm để thực hiện thuật toán trong thử thách, vì vậy tôi muốn tìm một lối tắt cho giải pháp. Trong khi tôi tìm thấy một điều, thật không may, nó không đánh bại câu trả lời Mathicala thực hiện thuật toán. Điều đó nói rằng, tôi chắc chắn rằng điều này chưa được đánh gôn tối ưu, và có thể có những ngôn ngữ khác có thể hưởng lợi từ phương pháp này hoặc một số hiểu biết thu được trong quá trình này.

Vì vậy, tôi khẳng định rằng chuỗi chúng ta phải tính toán là:

f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)

Ngoài ra, đó là f (n) = 1 nếu n là số tam giác và f (n) = 2 * ( A212652 (n) - A002024 (n) + 1) nếu không.

Trong biểu thức đầu tiên, A023532 chỉ đơn giản mã hóa hai trường hợp khác nhau này. Hai dãy còn lại (cộng 1) là sự khác biệt giữa số nguyên k lớn nhất trong phép phân tách dài nhất của n thành các số nguyên liên tiếp (k-i + 1) + (k-i + 2) + ... + k = n và số nguyên j lớn nhất sao cho 1 + 2 + ... + j <n .

Nói một cách đơn giản hơn một chút, đây là cách chúng ta tìm thấy câu trả lời cho số phi tam giác: thứ nhất, tìm ra số tam giác lớn nhất T j đó là ít hơn n . Thì j là số nguyên áp chót được thêm vào trong bước 1 (vì sau khi thêm j + 1, chúng ta sẽ vượt quá n ). Sau đó phân tách n thành số nguyên liên tiếp (hoặc càng nhỏ) càng tốt và gọi cực đại trong số các số này k . Kết quả chỉ đơn giản là 2 * (kj) . Lý do trực quan cho điều này là vì tối đa trong phân tách tăng thêm 1 bước khác và chúng ta dừng lại khi đạt đượck .

Chúng ta cần chỉ ra bốn điều để chứng minh rằng điều này hoạt động:

  1. f (n) = 1 cho các số tam giác. Đây là trường hợp tầm thường, bởi vì bước đầu tiên chỉ đơn giản là lặp qua tất cả các số tam giác. Nếu chúng tôi đạt được n chính xác trong quá trình này, chúng tôi đã hoàn thành và chỉ có một bước để tính toán.
  2. Đối với tất cả các số khác, chúng tôi luôn kết thúc sau một bước xóa, không bao giờ sau bước chèn. Điều đó có nghĩa là tất cả các f (n) khác đều chẵn.
  3. Trong mỗi bước chèn sau bước đầu tiên, chúng tôi chỉ thêm một số duy nhất. Điều này đảm bảo rằng chúng ta sẽ đạt được phân tách bao gồm k sau các bước kj .
  4. Phân rã cuối cùng của n mà chúng ta thu được luôn là phân rã dài nhất có thể của n thành các số nguyên liên tiếp, hay nói cách khác, nó luôn luôn là phân rã của n với cực đại thấp nhất trong số các số tổng. Nói cách khác, số cuối cùng chúng ta thêm vào tổng luôn là A212652 (n) .

Chúng tôi đã chỉ ra tại sao (1) là đúng. Tiếp theo, chúng tôi chứng minh rằng chúng tôi không thể kết thúc ở bước chèn trừ bước đầu tiên (điều này không xảy ra đối với các số không phải là hình tam giác).

Giả sử chúng ta đã kết thúc ở bước chèn, đạt n sau khi thêm giá trị p vào tổng. Điều đó có nghĩa là trước bước chèn này, giá trị là np ( hoặc ít hơn nếu chúng ta thêm nhiều giá trị cùng một lúc). Nhưng bước chèn này được đi trước bởi một bước xóa (vì chúng ta không thể nhấn n trong bước 1). Giá trị cuối cùng q chúng tôi đã loại bỏ trong bước xóa này nhất thiết phải nhỏ hơn p do cách thức hoạt động của thuật toán. Nhưng điều đó có nghĩa là trước khi loại bỏ q, chúng ta có n-p + q ( hoặc ít hơn ) nhỏ hơn n. Nhưng đó là một mâu thuẫn, bởi vì chúng tôi sẽ phải ngừng xóa số nguyên khi chúng tôi nhấn n-p + q thay vì xóa q khác . Điều này chứng tỏ điểm (2) ở trên. Vì vậy, bây giờ chúng tôi biết rằng chúng tôi luôn kết thúc ở bước xóa và do đó tất cả các số không phải là tam giác đều có đầu ra.

Tiếp theo, chúng tôi chứng minh (3), rằng mỗi bước chèn chỉ có thể chèn một giá trị. Đây thực chất là một hệ quả của (2). Chúng tôi đã chỉ ra rằng sau khi thêm một giá trị, chúng tôi không thể đạt n chính xác và vì chứng minh đã sử dụng bất đẳng thức, chúng tôi cũng không thể kết thúc dưới n (kể từ đó n-p + q vẫn sẽ nhỏ hơn n và chúng tôi không nên xóa mà nhiều giá trị ở nơi đầu tiên). Vì vậy, bất cứ khi nào chúng tôi thêm một giá trị, chúng tôi đảm bảo vượt quá n vì chúng tôi đã xuống dưới n bằng cách xóa một giá trị nhỏ hơn. Do đó, chúng ta biết rằng đầu trên của tổng tăng thêm 1 mỗi bước khác. Chúng tôi biết giá trị ban đầu của phần trên này (nó là m nhỏ nhất sao choT m > n ). Bây giờ chúng ta chỉ cần tìm ra phần cuối này khi chúng ta đã đạt được số tiền cuối cùng. Sau đó, số lượng các bước chỉ đơn giản là gấp đôi sự khác biệt (cộng 1).

Để làm điều này, chúng tôi chứng minh (4), tổng cuối cùng luôn là phép phân tách n thành càng nhiều số nguyên càng tốt hoặc phân tách trong đó mức tối đa trong phân tách đó là tối thiểu (nghĩa là phân tách sớm nhất có thể). Một lần nữa chúng ta sẽ làm điều này bằng mâu thuẫn (từ ngữ trong phần này có thể khắt khe hơn một chút, nhưng tôi đã dành quá nhiều thời gian cho việc này ...).

Nói rằng sự phân tách sớm nhất / dài nhất có thể của n là một số a + (a + 1) + ... (b - 1) + b , a b và nói thuật toán bỏ qua nó. Điều đó có nghĩa là tại thời điểm b được thêm vào, a không còn là một phần của tổng. Nếu a là một phần của tổng s , thì chúng ta sẽ có n tại thời điểm đó. Vì vậy, tổng chỉ chứa các giá trị từ a đến b , bằng n và chúng ta dừng lại (do đó chúng ta không bỏ qua phép phân tách này) hoặc có ít nhất một giá trị nhỏ hơn a trong tổng, thắng trường hợp nào n <svà giá trị đó sẽ bị xóa cho đến khi chúng tôi đạt được tổng chính xác (một lần nữa, quá trình phân tách không bị bỏ qua). Vì vậy, chúng ta phải loại bỏ a trước khi thêm b . Nhưng điều đó có nghĩa là chúng ta sẽ phải đạt đến một tình huống trong đó a là thành phần nhỏ nhất của tổng và lớn nhất chưa phải là b . Tuy nhiên, tại thời điểm đó, chúng tôi không thể xóa a , vì tổng rõ ràng nhỏ hơn n (vì b bị thiếu), vì vậy chúng tôi bắt buộc phải thêm giá trị trước cho đến khi chúng tôi thêm b và nhấn n chính xác. Điều này chứng tỏ (4).

Vì vậy, kết hợp những điều này lại với nhau: chúng ta biết rằng cặp bước đầu tiên mang lại cho chúng ta giá trị tối đa là A002024 (n) . Chúng tôi biết rằng giá trị tối đa của phân tách cuối cùng là A212652 (n) . Và chúng tôi biết rằng mức tối đa này được tăng lên một lần trong mỗi cặp bước. Do đó, biểu thức cuối cùng là 2 * ( A212652 (n) - A002024 (n) + 1) . Công thức này hầu như hoạt động đối với các số tam giác, ngoại trừ với những người chúng ta chỉ cần 1 bước thay vì 2, đó là lý do tại sao chúng ta sửa kết quả với hàm chỉ thị của các số tam giác (hoặc nghịch đảo của nó, bất kỳ thuận tiện hơn).

Cuối cùng, như để thực hiện. Đối với chuỗi trước, tôi đang sử dụng công thức MIN (lẻ d | n; n / d + (d-1) / 2) từ OEIS. Hóa ra là tiết kiệm một vài byte nếu chúng ta lấy hệ số 2 vào biểu thức này để lấy MIN (lẻ d | n; 2n / d + d-1) , vì -1 đó sẽ hủy +1 trong phiên bản đầu tiên của tôi của f (n) mã hóa trực tiếp hai trường hợp cho số tam giác và không tam giác. Trong mã, đây là:

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]

Đối với chuỗi sau ( 1, 2, 2, 3, 3, 3, ...), chúng ta có thể sử dụng một dạng đóng đơn giản:

⌊(2#)^.5+.5⌋

Và cuối cùng, hàm chỉ thị nghịch đảo của các số tam giác là 0 bất cứ khi nào 8n + 1 là một hình vuông hoàn hảo. Điều này có thể được thể hiện trong Mathicala như

⌈Sqrt[8#+1]~Mod~1⌉

Có rất nhiều cách để thể hiện hai chuỗi cuối cùng này và thay đổi một số bù trừ không đổi giữa chúng, vì vậy tôi chắc chắn đây chưa phải là một triển khai tối ưu, nhưng tôi hy vọng điều này có thể giúp người khác bắt đầu xem xét các cách tiếp cận mới trong ngôn ngữ riêng của họ.

Vì tôi đã đi đến tất cả những rắc rối này, đây là một chuỗi của chuỗi lên tới n = 1000 (tôi cũng có thể tính toán 100k trong vài giây, nhưng nó không thực sự hiển thị bất kỳ thông tin chi tiết bổ sung nào):

nhập mô tả hình ảnh ở đây

Có thể rất thú vị khi xem xét các biến thể về những đường thẳng đó, nhưng tôi sẽ để nó cho người khác ...


Cuối cùng tôi đã dành thời gian để đọc kỹ câu trả lời của bạn. Điều này thật tuyệt vời. Lưu ý rằng (3) đã được giả định trong thuật toán (bước # 3 là nếu , không phải là một thời gian ), nhưng bằng chứng là - tất nhiên - rất được hoan nghênh.
Arnauld

@Arnauld Cảm ơn bạn. :) Tôi đã bỏ qua / hiểu nhầm phần if / while. Điều tốt là nó không tạo ra sự khác biệt sau đó.
Martin Ender

7

Toán học, 72 byte

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

Hàm thuần túy lấy một đối số nguyên.

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

For[ ... ]

Một Forvòng lặp.

l=u=c=k=0

Khởi tạo; đặt l(dưới), u(trên), c(bộ đếm) và k(tổng) thành 0.

k!=#

Điều kiện; lặp lại trong khi kkhông bằng đầu vào.

c++

Tăng; tăng bộ đếm c.

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

Thân hình

If[#>k, ... ]

Nếu đầu vào lớn hơn k:

While[#>k,k+=++u]

Trong khi đầu vào lớn hơn k, tăng uvà tăng ktheo u.

Nếu đầu vào không lớn hơn k:

While[#<k,k-=l++]

Trong khi đầu vào là ít hơn k, sụt lần kbằng lvà thặng dư l.

( ... ;c)

Quay trở lại csau vòng lặp.


1
For[,...]nhịp đập While[...].
Martin Ender

5

Python 2 , 104 byte

N=input();i=s=0;l=()
while N!=sum(l):exec'while sum(l)'+['<N:i+=1;l+=i,','>N:l=l[1:]'][s%2];s+=1
print s

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

Thay thế giữa việc thêm các điều khoản vào cuối danh sách và xóa các điều khoản từ đầu.


5

Haskell , 70 63 68 64 byte

CHỈNH SỬA:

  • -7 byte: Loại bỏ một khoảng trắng, hai dấu hiệu và một số dấu ngoặc đơn bằng cách phủ định ý nghĩa của a. Đã sửa lỗi off-by-one trong phần giải thích.
  • +5 byte: Argh, đã bỏ lỡ hoàn toàn yêu cầu 65536 và hóa ra (1) sức mạnh của 2 là đặc biệt đắt đỏ, bởi vì chúng chỉ bị tấn công khi bạn nhận được chính số đó (2) nên tổng hợp các khoảng dài (bao quanh không) tất cả các thời gian. Thay thế tổng bằng một công thức toán học.
  • -4 byte: Được điều chỉnh abtuyến tính để lấy các số hạng trong công thức tính tổng để hủy.

1#1 là một hàm ẩn danh lấy và trả về một số nguyên.

Sử dụng như (1#1) 100.

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

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

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

  • (a#b)nđại diện cho bước tính toán hiện tại. a, blà các số trong 1, 3, 5, .., trong khi ncó thể là dương hoặc âm tùy theo bước.
    • Khi ở bước 1 hoặc 3, nó đại diện cho danh sách [(a+1)/2,(a+3)/2..(b-1)/2]và số mục tiêu -n.
    • Khi ở bước 2, nó đại diện cho danh sách [(b+1)/2,(b+3)/2..(a-1)/2]và số mục tiêu n.
  • Sự tương ứng kỳ lạ giữa a, bvà các danh sách là để có thể thực hiện tổng kết với biểu thức ngắn s=a*a-b*b.
    • Trong bước 1 và 3, điều này giống như s= -8*sum[(a+1)/2..(b-1)/2].
    • Ở bước 2, điều này giống như s=8*sum[(b+1)/2..(a-1)/2].
  • Sự phân nhánh được thực hiện bằng cách có các danh sách hiểu được tạo ra các phần tử chỉ trong một trường hợp và tổng hợp kết quả.
    • Nếu s>8*n, sau đó bđược tăng thêm 2 trước khi đệ quy.
      • Trong bước 1 và 3, điều này phát triển danh sách, trong khi ở bước 2, điều này thu nhỏ nó.
    • Nếu s<8*n, sau đó đệ quy thay đổi bước bằng cách hoán đổi ab, và phủ định n, và 1 được thêm vào kết quả.
    • Nếu s==8*n, thì cả hai cách hiểu danh sách đều đưa ra bất kỳ yếu tố nào, vì vậy tổng là 0.
  • (1#1) nđại diện cho một "giai đoạn 2" giả trước khi bắt đầu, ngay lập tức được thay đổi sang bước 1, xây dựng danh sách từ đó [1..0]=[].

4

PHP> = 7.0, 74 byte

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

sử dụng toán tử tàu vũ trụ

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

Mở rộng

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps

Có gì $argn?
chx

@chx Một biến chỉ xuất hiện khi bạn bạn PHP từ dòng lệnh với -R Lựa chọn php.net/manual/en/features.commandline.options.php
Jörg Hülsermann

Ồ Tôi chưa bao giờ nghe về -Rít argvhoặc nhiều argi. Tôi biết về argc và argv tất nhiên. Rất thú vị, cảm ơn.
chx

4

C, 94 91 byte

Thử trực tuyến

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}

Sử dụng rộng rãi trên các biến chưa được khởi tạo oO
YSC

@YSC trong C, số nguyên chưa được khai báo trên toàn cầu được đặt thành 0 tại thời điểm biên dịch. đọc thêm
Khaled.K

Quên về điều này. Cảm ơn vì lời nhắc này.
YSC

FYI, tôi đã đăng một câu trả lời C khác . Ít nhất một trong những thủ thuật tôi đã sử dụng sẽ không hoạt động với các trình biên dịch khác (thiếu return), nhưng đối với những trình biên dịch đó, hãy thoải mái kết hợp chúng vào câu trả lời của bạn.
hvd

3

JavaScript (ES6), 82 byte

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

Kiểm tra đoạn trích


Xin lỗi để nói điều này, nhưng mỗi được tính là 3 byte. Tôi đoán nó không thành vấn đề vì nó có thể thay đổi tầm thường.
Ørjan Johansen

@ RjanJohansen Cảm ơn đã nhắc nhở tôi. Tôi thực sự nên nhớ ghi điểm mã của mình theo byte chứ không phải theo độ dài. Tôi không nghĩ rằng có một sự đồng thuận của cộng đồng về "các biến [tầm thường] có thể thay đổi một cách tầm thường nên tôi đã chỉnh sửa bài đăng. Ồ tốt
R. Kap

3
Đoạn trích không thành công với Hồi quy quá nhiều Hồi quy trên 6553. 6553 hoạt động ở Node (6.9.1) cục bộ, nhưng 65536 không (Kích thước ngăn xếp cuộc gọi tối đa vượt quá).
eush77

3

dc , 61 byte

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

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

Giải trình

Macro đệ quy chính:

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

Macro này:

  1. Tìm số tam giác tối thiểu vượt quá số hiện tại trên ngăn xếp (sử dụng công thức gốc tam giác đã sửa đổi ).
  2. Kiểm tra nếu tổng tam giác Sthể hiện chính xác số hiện tại. Thoát nếu nó làm.
  3. Chuyển sang bước 1 với S+N(xấp xỉ quá mức) hoặc S-N(dưới xấp xỉ), lựa chọn xen kẽ giữa các lần lặp.

Khi nó thoát, dấu vết còn lại trên ngăn xếp cho chương trình chính biết nó đã thực hiện bao nhiêu lần lặp.


3

Python 3, 150 138 byte

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

Thay đổi:

  • Đã thay đổi nối vào + =, đã xóa khác (cảm ơn musicman523, Loovjo; -12 byte)

1
Bước # 2 có thể xóa một hoặc một số thuật ngữ cùng một lúc khỏi danh sách (như 1, 2 và 3 trong ví dụ cho N = 11) nhưng được tính là một bước theo một trong hai cách.
Arnauld

@Arnauld bỏ qua điều đó; đã sửa.
L3viathan

1
Bạn có thể giải thích tại sao elsecần thiết? Tôi tin rằng các elselần chạy mỗi lần, bởi vì vòng lặp luôn kết thúc bình thường (không có break) và dường nhưhoạt động tốt mà không có nó .
sĩ523

Bạn có thể bỏ qua A=l.appendphần và sử dụng l+=[x]thay thế.
Loovjo

3

Mẻ, 126 byte

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

Giải thích: lbằng không nếu bước 2 chưa bao giờ thực hiện. Điều này cho phép ntheo dõi số lần lặp của bước 3. Vì thuật toán không bao giờ dừng ở bước 3, do đó, nó phải chạy bước 1 một lần và bước 2 n+1lần trong tổng số n+n+2bước. Tuy nhiên, nếu tham số là số tam giác thì bước 2 không bao giờ thực hiện nên chúng ta cần trừ đi một bước.


3

Python 2, 86 81 byte

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

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

Tính toán trường hợp kiểm tra 65536 trong 0.183sTIO.


Phiên bản đệ quy ở 84 byte này không thể tính toán tất cả các giá trị lên tới 65536:

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

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


2

Toán học, 92 byte

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

Hàm thuần túy lấy một đối số nguyên và trả về một số nguyên.

Các biến avà viết btắt của các số bắt đầu và kết thúc (liên tục thay đổi) trong tổng số đang xem xét, trong khi đó qlà viết tắt của tổng số đang chạy (của các số từ a+1đến b); ttheo dõi tất cả các giá trị qgặp phải cho đến nay. Sau khi khởi tạo các biến này, Forvòng lặp tiếp tục thực thi If[q<#,q+=++b,q-=++a], sẽ thêm một số mới vào cuối hoặc trừ số ở phía trước như được chỉ định bởi thông số kỹ thuật, cho đến khi qbằng với đầu vào.

Bây giờ chúng ta chỉ cần trích xuất số bước từ t, danh sách các qgiá trị gặp phải trên đường đi. Ví dụ, khi đầu vào là 11, Forvòng lặp thoát với tbằng {0,1,3,6,10,15,14,12,9,15,11}. Cách tốt nhất tôi tìm thấy để tính toán số bước từ đây là tính số lần chuyển đổi từ đi lên xuống; đó là những gì lệnh verbose Length@Split@Sign@Differences@tlàm, nhưng tôi nghi ngờ rằng nó có thể được cải thiện.


2

C (tcc), 71 byte (61 + 10)

Đối số dòng lệnh (bao gồm cả khoảng trắng):

-Dw=while

Nguồn:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

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

cđếm số bước. mMlưu trữ tối thiểu và tối đa của phạm vi, stổng. Ban đầu, tất cả đều bằng không.

Liên tục, cđược tăng lên, và sđược so sánh với n. Miễn là chúng không bằng nhau:

  • Nếu clà số lẻ, thì miễn là s<nthêm một số nguyên vào cuối phạm vi: tăng thêm Mmột và sbằng M.

  • Nếu clà chẵn thì miễn là s>nxóa một số nguyên khỏi đầu phạm vi: giảm stheo mvà tăng mmột.

Khi vòng lặp thoát, cđã được tăng quá nhiều lần. Việc giảm nó tạo ra kết quả chính xác và nó được tính toán trong thanh ghi chính xác để đóng vai trò là giá trị trả về.

Thật thú vị khi sử dụng các tên biến chính xác giống như câu trả lời C của Khaled.K . Họ không sao chép.


1

Perl 6 , 114 byte

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(lấy cảm hứng từ một triển khai Haskell trước đó )

Dùng thử
Nó chạy với đầu vào 65536 trong dưới 45 giây trên máy tính của tôi, nhưng tôi không thể để nó chạy trong dưới 60 giây với TIO.run.
Tôi có Rakudo v2017.04 +, trong đó nó có v2017.01 .
Rakudo / NQP / MoarVM được tối ưu hóa gần như hàng ngày, do đó, có thể có bất kỳ số nào trong số chúng từ tạm thời cần thiết để có được nó theo thời gian.


Mở rộng

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

Lưu ý rằng Rakudo có tối ưu hóa để Range.sumkhông phải lặp lại tất cả các giá trị.

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.