Đây có phải là con số?


38

Nhiệm vụ

Đưa ra một số tự nhiên làm đầu vào, nhiệm vụ của bạn là đưa ra một giá trị trung thực hoặc falsey dựa trên việc liệu đầu vào là một yếu tố của bất kỳ số tự nhiên nào. Bạn có thể giả định rằng số đầu vào sẽ luôn nằm trong phạm vi số được hỗ trợ bởi ngôn ngữ của bạn, nhưng bạn không được lạm dụng các loại số gốc để tầm thường hóa vấn đề .

Áp dụng sơ hở tiêu chuẩn .


Đầu vào

Bạn sẽ được cung cấp một số tự nhiên (loại Integerhoặc tương tự).

Bạn có thể nhận đầu vào theo bất kỳ cách nào bạn muốn ngoại trừ giả sử nó nằm trong một biến được xác định trước. Đọc từ tập tin, bàn điều khiển, hộp thoại ( prompt), hộp đầu vào, vv được cho phép. Đầu vào là đối số chức năng cũng được cho phép!


Đầu ra

Chương trình của bạn sẽ xuất ra một giá trị trung thực hoặc falsey dựa trên việc số đầu vào là một yếu tố của bất kỳ số tự nhiên nào.

Đảm bảo rằng các giá trị trung thực / falsey của bạn phù hợp với tất cả các đầu vào, nghĩa là, nếu bạn đang sử dụng cặp 1 và 0 để biểu thị các giá trị trung thực và falsey tương ứng, thì chương trình của bạn phải xuất 1 cho tất cả các đầu vào có giá trị trung thực và 0 cho tất cả các đầu vào nên có giá trị falsey.

Bạn có thể lấy đầu ra theo bất kỳ cách nào bạn muốn ngoại trừ ghi nó vào một biến. Viết vào tập tin, bàn điều khiển, màn hình, vv được cho phép. Chức năng returncũng được cho phép!

Chương trình của bạn không được tạo ra lỗi cho bất kỳ đầu vào!


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

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

Tiêu chí chiến thắng

Đây là , vì vậy mã ngắn nhất tính bằng byte sẽ thắng!


2
Nếu ngôn ngữ chỉ hỗ trợ các số trong phạm vi {0,1}, tôi có thể mong đợi đầu vào luôn luôn 1không?
eush77

11
@ eush77 Việc lạm dụng các loại số gốc để tầm thường hóa một vấn đề bị cấm theo mặc định.
Dennis

1
là 4! một sự thật?
tuskiomi

Câu hỏi: Tại sao bạn không sử dụng mặc định I / O?
Máy

Câu trả lời:


37

Brachylog , 1 byte

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

Giải trình

là một tích hợp sẵn khẳng định mối quan hệ sau: đầu ra của nó là giai thừa của đầu vào của nó. Chúng tôi chỉ đơn giản cung cấp cho nó một đầu ra được thiết lập và xem liệu nó có thành công hay không với một đầu vào biến.


6
@BetaDecay Đó là vì đó là cách nó được in trong Prolog (điều này có liên quan đến thực tế đó true.là một tuyên bố và truekhông phải)
Fatalize

6
Đó là một giải pháp tầm thường, nhưng nó thông minh vì cách hoạt động của prolog.
Quả Esolanging


17
Ngôn ngữ tùy chỉnh đầu tiên, sau đó mã hóa tùy chỉnh ... mã golf đã chết. Chúng tôi đã hoàn toàn lật đổ toàn bộ vấn đề thú vị này ngay từ đầu
Alexander

13
@Alexander Mã hóa tùy chỉnh không liên quan đến bất kỳ vấn đề nào bạn đang nói đến. Tôi có thể sử dụng bất kỳ mã hóa "hiện có" nào và nó vẫn sẽ là 1 byte. Nó sẽ chỉ là ít đọc hơn nhiều.
Gây tử vong vào


19

Thạch , 4 byte

Œ?IE

Không phải là câu trả lời ngắn nhất của Jelly, nhưng nó khá hiệu quả.

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

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

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.

2
Bởi vì chúng tôi mã golf quan tâm đến hiệu quả.
Okx

12
Đó là một cải tiến phức tạp đáng kinh ngạc với chi phí là một byte và đó là cách sử dụng thông minh tích hợp nếu tôi có thể tự nói như vậy. ¯ \ _ (ツ) _ / ¯
Dennis

Thật thú vị, điều này trả về true cho 0, trong khi câu trả lời 3 byte của @ LeakyNun, trong khi nói chung chậm hơn nhiều, trả về sai cho 0. Có phải các byte bổ sung cần trả về false cho 0 trong câu trả lời thời gian thực hiện hiệu quả không?
Deadcode

@Deadcode Kiểm tra 0 sẽ yêu cầu thêm hai byte. Nếu không chắc chắn định nghĩa "số tự nhiên" của OP có bao gồm 0 hay không. Các trường hợp thử nghiệm không ...
Dennis

17

ECMAScript Regex, 733+ 690+ 158 119 118 (117🐌) byte

Sự quan tâm của tôi đối với regex đã được khơi dậy với sức sống mới sau hơn 4 năm không hoạt động. Do đó, tôi đã tìm kiếm các bộ số và hàm số tự nhiên hơn để phù hợp với các biểu thức ECMAScript đơn nhất, tiếp tục cải thiện công cụ regex của mình và cũng bắt đầu cải tiến trên PCRE.

Tôi bị mê hoặc bởi sự xa lạ của việc xây dựng các hàm toán học trong biểu thức ECMAScript. Các vấn đề phải được tiếp cận từ một quan điểm hoàn toàn khác, và cho đến khi có một cái nhìn sâu sắc quan trọng, không biết liệu chúng có thể giải quyết được không. Nó buộc phải đúc một mạng lưới rộng hơn nhiều trong việc tìm ra các thuộc tính toán học nào có thể được sử dụng để làm cho một vấn đề cụ thể có thể giải quyết được.

Kết hợp các số yếu tố là một vấn đề tôi thậm chí không cân nhắc việc giải quyết trong năm 2014 - hoặc nếu tôi đã làm, chỉ trong giây lát, loại bỏ nó là điều quá khó có thể xảy ra. Nhưng tháng trước, tôi nhận ra rằng nó có thể được thực hiện.

Cũng như các bài đăng regex ECMA khác của tôi, tôi sẽ đưa ra một cảnh báo: Tôi đặc biệt khuyên bạn nên học cách giải quyết các vấn đề toán học đơn phương trong biểu thức chính của ECMAScript. Đó là một hành trình hấp dẫn đối với tôi và tôi không muốn làm hỏng nó cho bất kỳ ai có khả năng muốn thử nó, đặc biệt là những người quan tâm đến lý thuyết số. Xem bài này sớm hơn để biết danh sách các vấn đề được đề xuất liên quan đến spoiler để giải quyết từng vấn đề một.

Vì vậy, đừng đọc thêm nữa nếu bạn không muốn một số phép thuật regex unary tiên tiến được làm hỏng cho bạn . Nếu bạn thực sự muốn tự mình tìm ra phép thuật này, tôi khuyên bạn nên bắt đầu bằng cách giải quyết một số vấn đề trong biểu thức ECMAScript như được nêu trong bài đăng được liên kết ở trên.

Đây là ý tưởng của tôi:

Vấn đề với việc khớp số này, như với hầu hết các số khác, là trong ECMA, thường không thể theo dõi hai số thay đổi trong một vòng lặp. Đôi khi chúng có thể được ghép kênh (ví dụ: các quyền hạn của cùng một cơ sở có thể được thêm vào một cách rõ ràng), nhưng nó phụ thuộc vào thuộc tính của chúng. Vì vậy, tôi không thể chỉ bắt đầu với số đầu vào và chia nó cho cổ tức tăng dần cho đến khi đạt 1 (ít nhất là tôi nghĩ vậy).

Sau đó, tôi đã thực hiện một số nghiên cứu về tính đa dạng của các thừa số nguyên tố trong các số nhân tử và biết rằng có một công thức cho điều này - và đó là một công thức mà tôi có thể thực hiện trong một biểu thức ECMA!

Sau khi hầm nó một lúc, và xây dựng một số regex khác trong thời gian đó, tôi nhận nhiệm vụ viết regex giai thừa. Phải mất một số giờ, nhưng cuối cùng đã làm việc tốt. Là một phần thưởng bổ sung, thuật toán có thể trả về yếu tố nghịch đảo như một trận đấu. Không có cách nào để tránh nó, thậm chí; bởi bản chất của cách nó phải được thực hiện trong ECMA, cần phải đoán xem yếu tố nghịch đảo là gì trước khi làm bất cứ điều gì khác.

Nhược điểm là thuật toán này tạo ra một regex rất dài ... nhưng tôi hài lòng rằng nó đã kết thúc đòi hỏi một kỹ thuật được sử dụng trong regex phép nhân 651 byte của tôi (một kết thúc bị lỗi thời, bởi vì một phương thức khác được tạo ra cho 50 regex byte). Tôi đã hy vọng một vấn đề sẽ xuất hiện đòi hỏi thủ thuật này: Hoạt động trên hai số, cả hai sức mạnh của cùng một cơ sở, trong một vòng lặp, bằng cách thêm chúng lại với nhau một cách rõ ràng và tách chúng ra ở mỗi lần lặp.

Nhưng vì độ khó và độ dài của thuật toán này, tôi đã sử dụng các bảng tìm phân tử (có dạng (?*...)) để thực hiện nó. Đó là một tính năng không có trong ECMAScript hoặc bất kỳ công cụ regex chính thống nào khác, mà là một tính năng mà tôi đã triển khai trong công cụ của mình . Không có bất kỳ ảnh chụp nào bên trong một cái nhìn phân tử, nó có chức năng tương đương với một cái nhìn nguyên tử, nhưng với các ảnh chụp thì nó có thể rất mạnh. Công cụ sẽ quay trở lại vào giao diện và điều này có thể được sử dụng để phỏng đoán một giá trị xoay quanh tất cả các khả năng (để kiểm tra sau) mà không tiêu tốn các ký tự của đầu vào. Sử dụng chúng có thể làm cho việc thực hiện sạch hơn nhiều. (Cái nhìn có chiều dài thay đổi có sức mạnh tối thiểu bằng với cái nhìn phân tử, nhưng cái sau có xu hướng tạo ra những triển khai đơn giản và thanh lịch hơn.)

Vì vậy, độ dài 733 và 690 byte không thực sự đại diện cho các hóa thân tương thích ECMAScript của giải pháp - do đó "+" sau chúng; chắc chắn có thể chuyển thuật toán đó sang ECMAScript thuần túy (sẽ tăng độ dài của nó lên một chút) nhưng tôi đã không tìm hiểu về nó ... bởi vì tôi nghĩ về một thuật toán đơn giản và gọn nhẹ hơn nhiều! Một trong đó có thể dễ dàng được thực hiện mà không cần nhìn phân tử. Nó cũng nhanh hơn đáng kể.

Cái mới này, giống như cái trước, phải đoán ở giai đoạn nghịch đảo, đạp xe qua tất cả các khả năng và kiểm tra chúng cho một trận đấu. Nó chia N cho 2 để nhường chỗ cho công việc cần thực hiện và sau đó gieo một vòng lặp trong đó nó sẽ liên tục chia đầu vào cho một ước số bắt đầu từ 3 và tăng mỗi lần. (Như vậy, 1! Và 2! Không thể khớp với thuật toán chính và phải được xử lý riêng.) Bộ chia được theo dõi bằng cách thêm nó vào thương số đang chạy; hai số này có thể được phân tách rõ ràng bởi vì, giả sử M! == N, thương số đang chạy sẽ tiếp tục chia hết cho M cho đến khi bằng M.

Regex này thực hiện chia từng biến trong phần trong cùng của vòng lặp. Thuật toán chia giống như trong các biểu thức chính khác của tôi (và tương tự như thuật toán nhân): với A≤B, A * B = C nếu có chỉ khi C% A = 0 và B là số lớn nhất thỏa mãn B≤C và C% B = 0 và (CB- (A-1))% (B-1) = 0, trong đó C là cổ tức, A là ước số và B là thương số. (Một thuật toán tương tự có thể được sử dụng cho trường hợp A≥B và nếu không biết A so với B như thế nào, thì một bài kiểm tra phân chia bổ sung là tất cả những gì cần thiết.)

Vì vậy, tôi thích rằng vấn đề có thể được giảm đến mức độ phức tạp thậm chí ít hơn so với biểu thức Fibonacci được tối ưu hóa cho môn đánh gôn của tôi , nhưng tôi thở dài với sự thất vọng rằng kỹ thuật ghép kênh đa năng của tôi sẽ phải chờ một vấn đề khác Điều đó thực sự đòi hỏi nó, bởi vì cái này không. Đó là câu chuyện về thuật toán nhân 651 byte của tôi được thay thế bằng một byte 50 byte, một lần nữa!

Chỉnh sửa: Tôi đã có thể giảm 1 byte (119 → 118) bằng cách sử dụng một mẹo được tìm thấy bởi Grimy có thể rút ngắn phân chia trong trường hợp thương số được đảm bảo lớn hơn hoặc bằng số chia.

Không có thêm rắc rối, đây là regex:

Phiên bản đúng / sai (118 byte):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

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

Trả về giai thừa nghịch đảo hoặc không khớp (124 byte):

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

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

Trả về giai thừa ngược hoặc không khớp, trong ECMAScript +\K (120 byte):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

Và phiên bản miễn phí với các bình luận:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

Lịch sử đầy đủ về tối ưu hóa golf của tôi về các biểu thức này là trên github:

regex để khớp các số giai thừa - phương pháp so sánh bội số, với
regex lookahead.txt phân tử để khớp các số giai thừa (một cách hiển thị ở trên)

((x*)x*)((x*)+)((x+)+)n=3!\233=0

Công cụ regex .NET không mô phỏng hành vi này trong chế độ ECMAScript của nó và do đó regex 117 byte hoạt động:

Hãy thử trực tuyến! (phiên bản làm chậm theo cấp số nhân, với công cụ regex .NET + mô phỏng ECMAScript)


14

JavaScript (ES6), 30 29 28 byte

Mong đợi một số nguyên dương. Trả về -1cho giả và -2cho sự thật.

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

Lưu ý : Hàm này hỗ trợ các đầu vào khá lớn (bạn nên đọc phần này dưới dạng: 'khá lớn cho JS'). Nó sẽ hoạt động an toàn lên đến 2 53 - 1 . Chắc chắn sẽ không bắt đầu từ N = 121,645,100,408,831,992 , đầu vào này được làm tròn thành 19! = 121.645.100.408.832.000 do mã hóa IEEE-754. Có thể có kết quả dương tính giả khác trước 121.645.100.408.831.991 do lỗi làm tròn, nhưng tôi không biết chắc chắn.


Đẹp - thực sự thích việc sử dụng ~ở cuối.
Steve Bennett

Bạn có thể chỉnh sửa để tôi có thể hoàn tác? (Nếu bạn muốn biết lý do tại sao tôi hạ cấp, đó là vì tôi đã quên quy tắc I / O bất thường của câu hỏi này.)
CalculatorFeline

@Arnauld Chưa được xác nhận.
Máy

11

Python 3 , 39 38 byte

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

Một hàm đệ quy chụp một số nguyên, n, trả lại một giá trị boolean inversley đại diện cho kết quả (truthy: False, falsey: True)

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

Liên tục chia ncho i, với giá trị ban đầu là 1, cho đến khi phần còn lại nhỏ hơn hoặc bằng 1kiểm tra nếu phần còn lại ít hơn 1, chỉ các giai thừa sẽ kết thúc với phần còn lại bằng 1<ngắn hơn một byte ==.


@ovs chúng tôi đã bị giới hạn ở hai đầu ra nhất quán. Điều đó, không may, trả lại 1cho tất cả các giai thừa trừ 1khi nó trả về True.
Jonathan Allan

11

Java 8, 46 byte

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

Điều này dựa trên mục nhập của Roman Gräf rằng tôi có thể loại bỏ hàng tá byte. Tôi đã đề nghị nó ở đó nhưng tôi không có đủ danh tiếng để bình luận! Mã chạy thử đã sửa đổi của tôi:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}

9

Võng mạc , 50 38 byte

12 byte được lưu nhờ @Neil bằng cách kết hợp rút ngắn vòng lặp và bằng cách loại bỏ ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

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

Đầu ra 1cho đúng và 0sai.

.+ khớp với toàn bộ số

1¶$&$*thay thế nó 1bằng một dòng mới và trận đấu được chuyển đổi thành unary

Chương trình còn lại chia số đơn vị ở dòng dưới cùng bằng cách tăng liên tục các số nguyên dương, theo dõi ở dòng trên cùng, trong khi có thể làm như vậy.

+` lặp cho đến khi chuỗi vẫn như cũ

  • ^(1+)¶(\1)+$phù hợp với dòng trên cùng nhiều 1s và bội số của nhiều 1dòng trên dòng dưới cùng và thay thế nó bằng dòng

  • 1$1¶$#2$*dòng trên cùng nhiều số 1khác 1, nghĩa là tăng số được biểu thị bằng dòng trên cùng bằng 1, theo sau là dòng mới và số lượng kết quả của dòng trên cùng trong dòng dưới cùng (ví dụ: số lượng trận đấu của nhóm bắt thứ hai ) nhiều 1s, nghĩa là chia số dưới cùng cho số trên cùng

Một khi nó không còn có thể làm như vậy,

¶.$đưa ra số lượng các trận đấu của regex này, tức là. có tồn tại một mình 1trên dòng dưới cùng, điều này chỉ xảy ra nếu số đó là một yếu tố


Nếu không cho phép sự cố / sự cố thay vì giá trị trung thực / giả, thì tôi có thể nhận được 36 34 byte.

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

Điều này đi theo cùng một cách tiếp cận, nhưng kết hợp $*thành dòng thứ ba và thứ tư. Dòng thứ ba trở đi là một phần của cùng một vòng lặp, {viết tắt là +(nơi các (nhóm các dòng còn lại vào vòng lặp. Các yếu tố kết thúc trong chương trình thoát ra khỏi vòng lặp, trong khi các yếu tố không liên tục bị mắc kẹt trong vòng lặp cho đến khi Retina ném OverflowException gây ra bởi sự thay thế cuối cùng thất bại, do đó có đáy ở dạng đơn nhất thay vì thập phân và thay thế đầu tiên của vòng lặp chuyển đổi dòng dưới cùng từ thập phân sang đơn nguyên, vì vậy nó sẽ nổ tung nhanh chóng.


Lưu một byte bằng cách loại bỏ 1như nó được ngụ ý khi $*ở cuối của sự thay thế.
Neil

Vẫn tốt hơn, kết hợp $*với hai dòng khác.
Neil


3
Tôi ấn tượng rằng bạn đã tìm ra cách để đánh bại Retina một cách có điều kiện. :)
Martin Ender

2
Bạn có thể thêm một lời giải thích?
Máy

8

05AB1E , 4 byte

L!QO

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

Giải trình

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum

1
Bạn không cần phải sao chép đầu vào trước vì Lbật đầu vào của nó? Ngoài ra, Å!cung cấp cho bạn một danh sách các giai thừa nhỏ hơn hoặc bằng đầu vào.
Neil A.

@NeilA. May mắn là đầu vào được bật lại nếu không có đủ đối số trên ngăn xếp cho một thao tác, vì vậy tôi không cần Dở đây. Bắt tốt về Å!. Tôi luôn quên về các lệnh danh sách. Nó sẽ không lưu bất kỳ byte nào, nhưng chắc chắn nó hiệu quả hơn.
Emigna

Tôi không biết về đầu vào được bật lại ... điều đó chắc chắn có thể tiết kiệm rất nhiều byte.
Neil A.

@NeilA. Đây là một tính năng khá mới. Nó đã được thêm vào chưa đầy một tháng trước.
Emigna

8

C ++, 102 100 92 byte

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

Vòng lặp thông qua tất cả các giá trị từ 0đến nvà tính giai thừa và sau đó kiểm tra xem nó có bằngn .

Cảm ơn Christoph! (đã lưu 8 byte)


Chào! Chào mừng đến với PPCG! Câu trả lời đầu tiên tốt đẹp! Chúc may mắn cho tương lai!
Arjun

Câu trả lời đầu tiên tốt đẹp! Bạn có thể lưu một vài byte như thế này : int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}. lroundlgammađã là C ++ 11 nên có thể đơn giản #include<cmath>. Có lẽ bạn thậm chí có thể cải thiện hơn nữa các đề xuất của tôi :)
Christoph

7

Haskell , 43 26 byte

f n=elem n$scanl1(*)[1..n]

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


2
f n=elem n$scanl1(*)[1..n]là vô lý không hiệu quả nhưng ngắn hơn.
Laikoni

Không có một số quy tắc về hiệu quả mã?
sudee

1
Không ai mà tôi biết. code-golf yêu cầu một giải pháp trong càng ít byte càng tốt mà không có bất kỳ tuyên bố hiệu quả nào. Ngoài ra trên máy của tôi, chức năng hoạt động lên đến mức 40430không có độ trễ đáng chú ý.
Laikoni

Tôi có nghĩa là một cái gì đó dọc theo dòng chữ "giải pháp nên chấm dứt trong một khung thời gian hợp lý", nhưng tôi đoán nó cũng phù hợp với các yêu cầu. Cảm ơn!
sudee

1
Đẹp và đơn giản. Tôi nghĩ rằng tôi có thể làm tốt hơn với sư đoàn nói, divModbằng cách [1..]liên tiếp cho đến khi đạt được phần còn lại bằng 0 với thương số 1 (giai thừa) hoặc phần còn lại không khác (không phải là yếu tố), nhưng dường như đó không phải là cách tiếp cận đúng. Tôi đã tìm thấy giải pháp 46 ký tự dễ thương này, mặc dù : f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%).
Jon Purdy

6

Haskell , 38 byte

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

Hãy thử trực tuyến! Ví dụ sử dụng : (2#) 24. Trả về Truehoặc False.

Đây là thời gian ngắn nhất tôi có thể nhận được trong khi vẫn rất hiệu quả. Ngay cả đối với số lượng lớn như

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

kết quả được đưa ra ngay lập tức. Các giải pháp làm việc bằng cách chia các đầu vào nbằng cách m = 2,3,4,5,...cho đến khi một trong hai kết quả là một hoặc nlà không chia hết cho m.

Đối với giải pháp 26 byte ngắn hơn nhưng không hiệu quả đáng kinh ngạc, tính toán n!cho các đầu vào không phải là yếu tố nhìn vào đây .



5

Fourier , 40 39 byte

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

Hãy thử nó trên FourIDE!

Về cơ bản nhân số N với số lượng tăng dần cho đến khi N bằng (đầu ra 1) hoặc lớn hơn (đầu ra 0) đầu vào.

Mã giả giải thích:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While

5

Japt , 8 6 byte

ol x¥U

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

Điều này xuất ra 0 cho sai và 1 cho đúng.

Giải trình

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result

1
Tôi thực sự nên thêm một "chứa" tích hợp: P
Sản phẩm ETH

1
Oh hey, bạn có thể thay đổi aU ¦Jđể x¥U(bản đồ từng Xđến X==Uvà tổng hợp), mặc dù nó sẽ không làm việc trên TIO.
Sản phẩm ETH

Thất bại cho 2becuase osẽ chỉ cung cấp cho bạn [0,1]. Đây là một sửa chữa với tiết kiệm 1 byte.
Xù xì

4

Perl 5, 31 byte

$a=<>;$a/=++$i while$a>1;exit$a

Đầu vào được lấy thông qua STDIN, đầu ra được đưa ra thông qua mã thoát (1 cho giai thừa, 0 cho không giai thừa).

Đầu vào được chia cho các số nguyên liên tiếp cho đến khi nó là 1 hoặc một số phân số nhỏ hơn một, được rút ngắn thành kết quả.



4

Perl 6 , 29 byte

{($_,{$_/++$}...2>*).tail==1}

Kiểm tra nó

Mở rộng:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}

17 byte : {$_∈[\*] 1..$_}. Một cách tiếp cận thú vị khác là 2>*.polymod(1..*).sum.
nwellnhof

4

setlX , 32 byte

f:=n|=>exists(x in{0..n}|n==x!);

Tạo một hàm gọi là f nơi bạn sử dụng giai thừa tiềm năng của bạn làm tham số.

Nó hoạt động với kích thước nguyên tùy ý nhưng nó khá kém hiệu quả.

(nhân tiện: đây là lần đầu tiên tôi tham gia vào một câu đố lập trình)




4

C # (.NET Core) , 68 byte

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

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

Không phải là giải pháp ngắn nhất, nhưng hoạt động với số lượng thực sự lớn. Liên kết TIO bao gồm một ví dụ với 10000!.

Đây là một phiên bản ngắn hơn sử dụng intcó giá trị tối đa là 2147483647 .

C # (.NET Core) , 45 byte

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

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

Tín dụng cho @KevinCruijssen để chơi golf tổng cộng 3 byte từ cả hai câu trả lời!


2
&&thể chơi gôn &và theo dõi ;không cần phải tính cho các hàm lambda. Ngoài ra, không ulong k=2thể có uint k=2trong câu trả lời 50 byte của bạn?
Kevin Cruijssen

1
Tốt bắt trên &vs &&. Tôi nghĩ rằng tôi đã nhận được một ngăn xếp tràn, nhưng nó dường như hoạt động sau đó. ulonglà 64 bit trong khi uintlà 32. Có vẻ như những người khác đang sử dụng intnên có lẽ tôi sẽ chỉ sử dụng nó cho phiên bản ngắn. Liên quan đến dấu vết ;, đây là các chức năng đầy đủ, không phải lambdas, vì vậy tôi nghĩ rằng tôi cần bao gồm chúng?
dana

Điều đó thực sự kỳ lạ khi .NET có thể giải quyết /%giữa ulonguint, nhưng không ulongint. Không biết điều đó :)
dana

1
@Oliver - Với doublebạn bắt đầu thấy làm tròn tại một số điểm - ví dụ: 24! và 120! Thất bại. Trong khi System.Numerics.BigIntegercó độ chính xác cao nhất, intlà câu trả lời ngắn nhất :)
dana

1
@Deadcode - Bạn nói đúng về 0 :) Dựa trên các ví dụ trong thử thách, tôi đã hiểu "số tự nhiên" có nghĩa là 1,2, ... Tôi đồng ý rằng trong thế giới thực, tốt hơn là sử dụng &&toán tử ngắn mạch . Nhưng đây là mã golf;) Vui mừng bạn thích 10000!ví dụ!
dana

4

C ++ (tiếng kêu), 51 byte

Recursion thắng ra xa như chơi golf.

51 byte, số không là đúng:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

Điều này hy sinh khá nhiều tốc độ cho 1 byte tiết kiệm. Thay thế |bằng ||để làm cho nó nhanh, do đánh giá ngắn mạch của logic OR.

Hãy thử trực tuyến! (Phiên bản chậm 51 byte)
Hãy thử trực tuyến!(Phiên bản nhanh 52 byte)

Ungolfed phiên bản chậm:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

Ungolfed phiên bản nhanh:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

Có nhiều cách để sắp xếp lại thứ này.

52 byte, khác không là đúng:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

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

52 byte, số không là đúng:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

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

Trước khi sử dụng đệ quy, tôi đã thử tạo một số phiên bản lặp lại và chúng đã kết thúc.

54 byte, khác không là đúng:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

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

54 byte, 0 là đúng (dựa trên đệ trình Java 8 của Roman Gräf ):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

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

Bây giờ, đối với đáy thùng, các phiên bản đệ quy không có n==0xử lý (tôi coi những điều này không hợp lệ, vì 0 là số tự nhiên và bất kỳ định nghĩa nào trong đó không tạo ra "số tự nhiên" cho việc sử dụng rất hạn chế). Trong các phiên bản dưới đây, đệ quy vô hạn củaf(0) một trong hai kích hoạt một segfault do tràn ngăn xếp hoặc với các trình biên dịch tối ưu hóa nó thành lặp, lặp lại vô tận:

48 byte, 0 là đúng:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

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

48 byte, 0 là đúng (dựa trên đệ trình 33 byte C (gcc) của Hagen von Eitzen ):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

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


50 EDIT: 49 , không có đệ quy.
Grimmy

Trở lại đệ quy cho 48 . Và bạn có thể sẽ không thích điều này, nhưng 44 bằng cách sử dụng var toàn cầu.
Grimmy

3

Toán học, 20 byte

!FreeQ[Range[#]!,#]&

phiên bản khác để kiểm tra số lượng lớn (xem bình luận)

Range[10^3]!~MemberQ~#&

kiểm tra lên tới 1000!


2
Theo tôi hiểu câu hỏi, nếu Mathematica có khả năng lấy 1001! như một đầu vào thì điều này không đáp ứng được thông số kỹ thuật.
Peter Taylor

2
Bạn thậm chí có thể lưu ba byte trong khi làm cho nó hợp lệ cho tất cả các đầu vào. Chỉ cần thay 10 ^ 3 bằng #; bạn có thể lưu một byte khác bằng cách sử dụng Range @ #
Julien Kluge

@Julien Klugethen tìm kiếm 1243234 sẽ mất mãi mãi ...
J42161217

1
Tôi nghĩ bạn có thể lưu một byte khác bằng cách thay thế Range[#]bằng Range@#:)
numbermaniac

3
Có vẻ như bạn có thể lưu một byte khác với cú pháp infix : !Range@#!~FreeQ~#&.
numbermaniac

3

Khối , 24 byte

U0O@1I1>-?1u>*w;W;@Orq)p

Dùng thử trực tuyến

Tạo khối

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

Chúng tôi bắt đầu bằng cách đẩy 1, Input,1 lên ngăn xếp. Đây sẽ là chỉ số của chúng tôi, mục tiêu và tích lũy của chúng tôi, tương ứng.

Chúng tôi sau đó lặp lại. Ở mỗi lần lặp, chúng tôi trừ đi bộ tích lũy từ đầu vào. Nếu kết quả là 0, chúng tôi đã hoàn thành, vì vậy chúng tôi đẩy 1, Omở rộng và thoát. Nếu đó là tiêu cực, chúng tôi đã đi quá xa, vì vậy chúng tôi đẩy 0, không Obiết và thoát. Mặt khác, chúng ta thấy

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.

3

Neim , 8 byte

𝐈Γ𝐈𝐩₁𝔼)𝐠

Giải trình:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

Thử nó!

Neim , 3 byte (không cạnh tranh)

Không cạnh tranh vì mã thông báo chứa và mã thông báo giai thừa đã được thêm vào sau khi thử thách được thực hiện.

𝐈𝐓𝕚

Giải trình:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

Thử nó!


3

> <> , 24 22 byte

-2 byte nhờ @Aaron

Tôi đang thử một ngôn ngữ mới (vì giấy phép Mathicala của tôi đã hết hạn)

01\{=n;
?!\$1+:@*:{:}(

Dùng thử trực tuyến hoặc tại sân chơi cá

Giả sử số đầu vào đã có trên ngăn xếp và trả về 0 hoặc 1. Nó hoạt động bằng cách nhân các số n đầu tiên với nhau cho đến khi số đó dừng nhỏ hơn đầu vào, sau đó in 1 nếu nó bằng đầu vào và 0 nếu nó không ' t.


Bạn có thể biến bạn v>\n<^thành \\n/; xem tại đây
Aaron

@Aaron, thật tuyệt vời, cảm ơn bạn!
Không phải là cây

3

APL (Dyalog Unicode) , 5 6 7 byte

Golfed một byte bằng cách thay đổi ×/để !nhờ Erik các Outgolfer

⊢∊!∘⍳

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

Giải trình

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?

Tổng tích lũy?
Nữ tu bị rò rỉ

@LeakyNun Đã sửa
Kritixi Lithos

Thêm một byte trong GNU APL 1.2 N∊×\⍳N←⎕Làm thế nào để có một đối số? Tôi không thấy ở nđâu cả. Đây có phải là một điều cụ thể của Dyalog?
Arc676

2
@ Arc676 Giải pháp của tôi là một chuyến tàu và bạn gọi nó như vậy: (⊢∊(×/⍳)) right_argumentnhư bạn có thể thấy trong liên kết TIO. Và đề cập đến các đối số đúng.
Kritixi Lithos

Ghi chú: AGL sẽ giúp bạn tiết kiệm một byte; ⊢∊×\ä⍳. Giải pháp "chính xác" (nhưng dài hơn) sẽ là 0=1|!⍣¯1; "Là giai thừa nghịch đảo là một số nguyên?"
Adám

2

JavaScript (ES6), 71 byte

Điều này nhận đầu vào là đối số chức năng và alerts đầu ra. Đầu ra 0cho falsey và 1cho sự thật.

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

Giải trình

Chương trình bao gồm hai chức năng, fg. flà một chức năng tính toán đệ quy, và glà chức năng chính của chương trình. g giả sử có một đối số duy nhất n. Nó định nghĩa một đối số mặc định rcó giá trị 0 và một đối số mặc định khác có giá trị là 0. Sau đó, nó lặp lại trên tất cả các số nguyên từ 0 đến nvà, trong mỗi lần lặp, kiểm tra xem hàm fđược áp dụng trên i(chỉ mục hiện tại) có bằng khôngn , tức là có phải nlà giai thừa của không i. Nếu đó là trường hợp, rgiá trị của được đặt thành 1. Ở cuối hàm, ralerted.

Kiểm tra đoạn trích

( Lưu ý: Các đầu ra đoạn trích sử dụng console.log()vì không ai thích quá nhiều những điều phiền phức alert()đó. )

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)


Eval có thể ngắn hơn so với sử dụng khối mã.
Hạ cấp

@Downgoat Tôi nên làm thế nào? Xin lỗi nếu nó quá rõ ràng! : P
Arjun

2

QBIC , 21 19 byte

[:|q=q*a~q=b|_x1}?0

Giải trình

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

Trước đây

[:|q=q*a┘c=c+(q=b)}?c

Giải trình:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.

2

Java 8, 59 byte

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

Mã kiểm tra

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
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.