Du hành thời gian chính


23

Đừng nói với ai, nhưng tôi đã đặt biệt danh cho cỗ máy du hành thời gian của chú tôi! Tuy nhiên, chú tôi bị ám ảnh bởi các số nguyên tố, và điều đó thể hiện trong máy - ông đã lập trình nó để nó chỉ có thể đi đến những ngày có tổng bằng số nguyên tố.

Vì vậy, nó không thể đi đến 1947-08-15vì 1947 + 8 + 15 = 1970, đây không phải là số nguyên tố. Nó có thể đi đến 1947-07-25, bởi vì 1947 + 7 + 25 = 1979, là số nguyên tố. Vì vậy, nếu tôi muốn quay lại để xem lễ kỷ niệm độc lập của Ấn Độ, có vẻ như tôi sẽ phải đi sớm hơn một vài tuần và chờ đợi 20 ngày đó.

Tôi có một số ngày khác mà tôi muốn đến và tương tự tôi sẽ phải đến một ngày trước đó (hoặc nếu tôi may mắn, bằng) ngày mục tiêu của tôi, tổng số đó là một số nguyên tố. Mặc dù vậy, tôi không kiên nhẫn và không muốn chờ đợi quá nhiều - vì vậy tôi muốn tìm ngày tôi có thể sử dụng gần nhất với ngày mục tiêu của mình.

Bạn có thể viết cho tôi một chương trình lấy ngày mục tiêu của tôi và cho tôi ngày tôi nên nhập vào cỗ máy thời gian - ngày gần nhất trước hoặc bằng với ngày đã cho có các phần cộng với số nguyên tố không?

(Đối với thử thách này, chúng tôi đang sử dụng lịch Gregorian phổ biến - điều này có nghĩa đơn giản là chúng tôi sử dụng lịch Gregorian hiện tại ngay cả trong những khoảng thời gian khi mọi người đang sử dụng lịch Julian cũ hơn.)

Đầu vào

  • Một buổi hẹn hò
    • lý tưởng, bất kỳ ngày nào trong Thời đại hiện tại (AD); thực tế, bất cứ tập hợp con nào của ngôn ngữ đó có thể tự nhiên xử lý
    • trong bất kỳ định dạng nào con người có thể đọc được - bạn thích

Đầu ra

  • Ngày gần nhất với ngày đầu vào, nhỏ hơn hoặc bằng đầu vào và có ngày + tháng + năm tính tổng bằng số nguyên tố.
    • trong bất kỳ định dạng nào con người có thể đọc được - bạn thích

: "Con người có thể đọc được" như trong ngày, tháng và năm được viết riêng, theo bất kỳ thứ tự nào

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

1947-08-15
=> 1947-07-25
1957-10-04
=> 1957-09-27
1776-07-04
=> 1776-07-04
999-12-12
=> 0999-12-10
2018-06-20
=> 2018-06-15
1999-01-02
=> 1998-12-29
1319-12-29
=> 1319-07-01

(Cảm ơn @Shaggy, @PeterTaylor và @Arnauld đã giúp đỡ với câu hỏi.)


Có ổn không khi có một thời gian vô nghĩa trong đầu ra? (ví dụ Fri Jul 25 02:46:39 CEST 1947)
lãng phí

@wastl Có, miễn là thông tin ngày là một chuỗi con có độ dài cố định liền kề của đầu ra (vì vậy không có ví dụ cụ thể nào).
- Phục hồi Monica

Câu trả lời:


4

Màu đỏ , 87 byte

func[d][d: d + 1 until[d: d - 1 n: d/2 + d/3 + d/4 i: 1 until[n %(i: i + 1)= 0]i = n]d]

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

Dễ đọc hơn:

f: func [ d ] [ 
    d: d + 1
    until [
        d: d - 1
        n: d/day + d/month + d/year
        i: 1
        until [
            i: i + 1
            n % i = 0
        ]
        i = n
    ] 
    d
]

4

JavaScript (Node.js) , 94 byte

Lấy đầu vào là 3 số nguyên trong cú pháp currying (year)(month)(day). Trả về một chuỗi được phân tách bằng dấu gạch nối với dấu gạch nối hàng đầu.

y=>m=>g=d=>(P=k=>n%++k?P(k):~k)(n=eval(s='-'+new Date(y,m-1,d).toJSON().split`T`[0]))?g(d-1):s

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

Làm sao?

Trước tiên, chúng tôi chuyển đổi ngày thành định dạng JSON yyyy-mm-ddT00:00:00.000Z( ISO 8601 ), phân tách nó trên 'T', chỉ giữ lại phần bên trái và thêm dấu gạch nối hàng đầu -yyyy-mm-dd.

s = '-' + new Date(y, m - 1, d).toJSON().split`T`[0]

Biểu thức này s bây giờ có thể được eval()'uated để có được điều ngược lại n số tiền của năm + tháng + ngày .

n = eval(s)

Chúng tôi sử dụng hàm trợ giúp P () để kiểm tra xem -n có phải là số nguyên tố hay không (trong trường hợp này nó trả về 0 ). Nếu có, chúng tôi trả lại s . Nếu không, chúng tôi thử lại với ngày hôm trước.

(P = k => n % ++k ? P(k) : ~k)(n) ? g(d - 1) : s

1
Tôi cảm thấy mình cần một ngày nghỉ chỉ để hiểu cách kiểm tra chính đó hoạt động và chấm dứt. Chơi golf tốt!
- Phục hồi Monica

3

Python 2 , 130 127 byte

Đầu vào là year, month, day.

-3 byte nhờ Kevin Cruijssen .

from datetime import*
def f(a):
  while(lambda n:any(n%m<1for m in range(2,n)))(a.year+a.month+a.day):a-=timedelta(1)
  print a

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


Bạn được phép lấy một đối tượng ngày làm đầu vào, vì vậy bạn có thể lưu 3 byte .
Kevin Cruijssen

1
@KevinCruijssen cảm ơn bạn. Bạn có nghĩ rằng đây là một định dạng đầu vào hợp lệ?
trứng

Tôi không hiểu tại sao nó lại như vậy, vì vậy đó là -4. Không nghĩ về điều đó.
Kevin Cruijssen

2

Java 8, 144 128 byte

d->{for(;;d=d.minusDays(1)){int n=d.getYear()+d.getMonthValue()+d.getDayOfMonth(),i=2;for(;i<n;n=n%i++<1?0:n);if(n>1)return d;}}

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

java.time.LocalDatelớp học đã là một sự cải tiến so với cái cũ java.util.Date, nhưng tại sao họ phải làm cho những cái tên đó dài hơn ( getMonthValuegetDayOfMonththay vìgetMonthgetDay) ..>.>

Giải trình:

d->{                      //  Method with LocalDate as both parameter and return-type
  for(;;                  //  Loop indefinitely
      d=d.minusDays(1)){  //    Going one day back after every iteration
    int n=d.getYear()+d.getMonthValue()+d.getDayOfMonth(),
                          //   Set `n` to the sum of year+month+day
    i=2;for(;i<n;n=n%i++<1?0:n);if(n>1)
                          //   If `n` is a prime:
      return d;}}         //    Return the now modified input-LocalDate `d`

2

Ruby , 94 byte

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

Lấy một đầu vào Ngày duy nhất và trả về một chuỗi ở định dạng ISO 8601 ( YYYY-MM-DD).

require'date'
require'prime'
->d{d.downto(0){|i|break i.to_s if (i.day+i.month+i.year).prime?}}

Nó sử dụng mô đun chính của Ruby. Nếu điều đó không được phép, hoặc nhăn mặt, thì thêm hai byte nữa tôi sẽ trình bày sự ghê tởm này:


Ruby , 97 byte

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

Nó sử dụng một kiểm tra cho một số là số nguyên tố từ câu trả lời stackoverflow này . Tôi không biết làm thế nào điều này hoạt động, nó trông hơi giống như phù thủy. Đầu vào giống như trên, và đầu ra tương tự.

require'date'
->d{d.downto(0){|i|break i.to_s if ?1*(i.day+i.month+i.year)!~ /^1?$|^(11+?)\1+$/}}

Sử dụng các mô-đun là hoàn toàn tốt miễn là các dòng nhập được bao gồm trong số byte (mà bạn đã thực hiện ở đây). Dường như bạn không cần các thông số xung quanh ban đầu dvà khoảng trắng sau ifđó, vì vậy bạn có thể tắt 3 byte khỏi câu trả lời đầu tiên của mình để loại bỏ các byte đó. Liên kết TIO
- Phục hồi Monica

3
Tôi thích sự ghê tởm phù thủy mặc dù. Nó khá gọn gàng và đơn giản khi bạn nhìn vào nó: ?x*n !~ /^x?$|^(xx+?)\1+$/= để kiểm tra xem n có phải là số nguyên tố hay không, tạo một chuỗi n 'x', kiểm tra xem nó không phải là 0 hay 1 x (không phải là số nguyên tố) và nó không khớp với bất kỳ 2 hoặc nhiều hơn x lặp lại chính nó (khớp ^(xxxxx)\1+$sẽ có nghĩa là n chia hết cho 5). Nó lạm dụng việc quay lại của động cơ regex để thực hiện vòng lặp cho chúng tôi - thật tuyệt vời, thật quái dị và sự hy sinh của động vật có lẽ liên quan đến khám phá của nó.
- Phục hồi Monica

Điểm tốt về dấu ngoặc đơn và không gian! Cảm ơn.
IMP1

Phiên bản "phù thủy" có thể được thực hiện trong 92 byte, xem tại đây . Vì tổng số tiền chúng tôi muốn kiểm tra tính nguyên thủy ít nhất là 3 (kể từ ngày tối thiểu 0001-01-01 tính tổng thành 1 + 1 + 1 = 3), chúng tôi có thể xóa phần regex dành riêng cho xử lý đầu vào là 0 hoặc 1. Loại bỏ điều đó và đơn giản hóa sẽ cho phiên bản 91 byte.
- Phục hồi Monica

Một cách tiếp cận thú vị. Lưu 2 byte bằng cách sử dụng 'mon' thay vì 'tháng'
GB

2

Ruby , 57 53 byte

->d{d-=9until/^(11+)\1+$/!~?1*(d.day+d.year+d.mon);d}

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

Không phải ý tưởng của tôi - bị đánh cắp từ "sự ghê tởm" của IMP1


Ý tưởng ban đầu:

Ruby , 59 byte

->d{d-=9until((2...w=d.day+d.year+d.mon).all?{|x|w%x>0});d}

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


1
8e4Thay vào đó sẽ sử dụng ?
Kritixi Lithos

Vâng, tất nhiên nó hoạt động. Nó cũng hoạt động bằng cách sử dụng 9 hoặc bất kỳ số nhỏ hơn nào khác. Nó chỉ mất nhiều thời gian hơn để chạy. Cảm ơn.
GB


2

F #, 134 133 byte

let rec s(d:System.DateTime)=
 let x=d.Year+d.Month+d.Day
 if(Seq.tryFind(fun i->x%i=0){2..x-1}).IsNone then d else d.AddDays(-1.)|>s

-1 byte nhờ từ Sundar .

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

Tổng số ngày, tháng và năm và xem nếu đó là số nguyên tố. Nếu có, hãy trả lại ngày đó. Nếu không, hãy giảm ngày 1 ngày và thử lại.


1
Bạn có thể lưu một byte bằng cách viết -1.0dưới dạng -1., trong lệnh gọi AddDays.
- Phục hồi Monica

Bạn nói đúng ... điều đó thực sự kỳ lạ. Nhưng hữu ích. Cảm ơn.
Ciaran_McCarthy

1

PowerShell , 105 90 byte

for($a=$args[0];'1'*((Date $a -f yyyy+MM+dd)|iex)-match'^(..+)\1+$';$a=$a.AddDays(-1)){}$a

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

Nhờ chủ nhật cho -13 byte.

Đưa đầu vào là một DateTime 2018-06-20và lưu nó vào $a. Sau đó, chúng tôi trong một forvòng lặp. Mỗi lần lặp, chúng tôi sẽ lấy $a -fhoặc được định dạng như yyyy+MM+dd(tức là ngày hiện tại chúng tôi được phân tách bằng +các dấu hiệu) được thêm vào cùng với |iex(tương tự eval), nhân chuỗi đó với 1s để tạo thành một số đơn nguyên và sử dụng biểu thức kiểm tra chính để xác định xem ngày hiện tại có phải là số nguyên tố hay không. Nếu nó không phải là số nguyên tố, chúng ta .AddDays(-1)sẽ lùi lại một ngày và tiếp tục vòng lặp. Nếu đó là số nguyên tố, chúng ta thoát ra khỏi vòng lặp và đặt $avào đường ống với đầu ra ngầm định.

Kết quả đầu ra phụ thuộc vào văn hóa. Trên TIO, sử dụng en-us, đầu ra là định dạng dài hạn, trông giống như Saturday, July 1, 1319 12:00:00 AM.


Bạn có thể lưu một vài byte bằng cách gửi đối số dưới dạng đối tượng datetime. Ngoài ra, regex có thể được đơn giản hóa để khớp các vật liệu tổng hợp trên 2 (vì ngày tối thiểu là 0001-01-01tổng của nó là 3). Tôi đã có một vết nứt tại những thay đổi ở đây .
- Phục hồi Monica

(lưu ý rằng tôi là người mới sử dụng năng lượng và mã được liên kết chỉ được thử nghiệm tối thiểu, thậm chí chưa từng thử tất cả các trường hợp thử nghiệm từ đây.)
sundar - Tái lập Monica

@sundar Tôi đã nghĩ về đầu vào đó, nhưng nó có vẻ hơi "gian lận" đối với tôi, vì vậy tôi đã đi với đầu vào chuỗi thay thế. Cảm ơn về mẹo trên regex - Tôi không hiểu đầy đủ về cách thức hoạt động của nó, vì vậy tôi chỉ mỉm cười và gật đầu khi nó xuất hiện. Hehe.
admBorkBork

1

Bash , 114 108 byte

a=`date +%s -d$1`
while [ "`date +%d+%m+%Y -d@$a|bc|factor|awk NF!=2`" ]
do a=$[a-86400]
done
date +%F -d@$a

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

Lần đầu tiên chơi golf của tôi. Thành thật mà nói, chương trình bash thực sự đầu tiên của tôi từng ... thử nghiệm nguyên thủy được thực hiện từ đây .

Điều này đôi khi có thể thất bại nếu có thay đổi múi giờ, nhưng TIO sử dụng UTC, do đó, nó sẽ hoạt động.


Là "9" trong dòng đầu tiên là một lỗi đánh máy? Loại bỏ điều đó và các trích dẫn xung quanh nó (vì chúng ta có thể yêu cầu đầu vào không được chứa khoảng trắng) và thêm một dấu ở cuối sau @$, cung cấp mã làm việc ở mức 110 byte .
- Phục hồi Monica

@sundar Tôi nghĩ rằng có thể có vấn đề với thời gian tiết kiệm ánh sáng ban ngày, nhưng tôi sẽ kiểm tra lại vào ngày mai
lãng phí

1

C (gcc) , 167 byte

r;P(n,i){for(r=0;++i<n;)r|=n%i<1;}f(y,m,d){for(;P(y+m+d,1),r;)!--d?d=" >8><><>><><>"[!--m?y--,m=12:m]/2+(m==2&!(y%4)&y%100|!(y%400)):0;printf("%04d-%02d-%02d",y,m,d);}

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

Chạy xuống

r;P(n,i){for(r=0;++i<n;)r|=n%i<1;}

Chức năng chống kiểm tra chính. Vì năm hợp lệ sớm nhất mà chúng tôi cần xử lý là 0001-01-01, con số thấp nhất chúng tôi cần lo lắng là 3, do đó, các trường hợp đặc biệt kiểm tra n == 2 hoặc n <2 bị loại bỏ. r được đặt thành giá trị trung thực nếu n không phải là số nguyên tố. r được giữ toàn cục, vì không phải trả về nên nó tiết kiệm hai byte ( i=n;để trả về so ,rvới kiểm tra toàn cục). i được đặt thành 1 bởi người gọi hàm, để lưu thêm 2 byte.

f(y,m,d){for(;P(y+m+d,1),r;)

Chúng tôi lấy ngày là ba số nguyên riêng biệt và bắt đầu vòng lặp chính, diễn ra cho đến khi y + m + d là số nguyên tố. Sau đó, chúng ta đến với thịt của chức năng:

!--d?                           Decrement day and check if zero, which means we go back to last day of previous month.
d=" >8><><>><><>"               The string contains the number of days of each month times 2, to bring them into printable ASCII range.
                                We begin the string with a space, to avoid having to substract from index later.
[!--m?y--,m=12:m]/2+            Decrement month and check if zero. If so, go back a year and set m to 12. Use m as index in string.
(m==2&!(y%4)&y%100|!(y%400))    If the new month is February, add 1 to day if it's a leap year.
:0;                             Do nothing if day did not become zero.

Có vẻ như iffy sử dụng m và y cả trong kiểm tra năm nhuận và là chỉ số của chuỗi, khi thứ tự đánh giá không được chỉ định. May mắn thay, chúng tôi chỉ kiểm tra năm nhuận nếu m == 2, điều này không thể xảy ra cùng lúc với chúng tôi thay đổi m và y, vì điều đó chỉ xảy ra từ tháng 1 đến tháng 12, vì vậy kiểm tra năm nhuận không bao giờ bị làm phiền bởi thứ tự đánh giá.

Cuối cùng, kết quả được in thành STDOUT:

printf("%04d-%02d-%02d",y,m,d);}

0

C # - 281 239 232 Char

using System;class P{static void Main(){var d=DateTime.Parse(Console.ReadLine());do{int c=d.Year+d.Month+d.Day;if(c%2!=0){int i=3;for(;i<=c;i+=2)if(c%i==0)break;if(i>=c)break;}d=d.AddDays(-1);}while(d>DateTime.MinValue);Console.WriteLine(d);}}

vô dụng:

using System;
class P
{
    static void Main()
    {
        var d = DateTime.Parse(Console.ReadLine());
        do
        {
            int c = d.Year + d.Month + d.Day;
            // minimum datetime in c# is 0001-01-01
            // therefore do not need to check for the first two primes 
            int i = 3;
            for (; i < c; i += 2) if (c % i == 0) break;
            // check to break the date decrement loop if counter passed the input value
            // ie, no factor could be found
            if (i >= c) break;

            d = d.AddDays(-1);
        } while (d > DateTime.MinValue);
        Console.WriteLine(d);
    }
}

Làm cho mã kém hiệu quả hơn nhưng nhỏ hơn. Vòng lặp Prime bây giờ sẽ đi lên số nguyên chứ không phải căn bậc hai. Nó cũng sẽ xử lý tất cả các số chẵn.


Bạn có thể loại bỏ public. Ngoài ra, vì dường như không được phép lấy đầu vào ngày làm tham số cuộc gọi, bạn có thể có Main(string[]a)và sau đóDateTime.Parse(a[0])
Corak

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.