프라임 타임 여행


23

아무에게도 말하지 말아라, 나는 나의 아저씨의 시간 여행 기계를 쳤다! 내 아저씨는 소수에 집착하고 기계에 표시됩니다. 그는 소수에 이르는 날짜로만 갈 수 있도록 프로그래밍했습니다.

따라서 1947-08-151947 + 8 + 15 = 1970이기 때문에 갈 수 없습니다 . 소수가 아닙니다. 이 에 가서 1947-07-251947 + 7 = 1979 + 25, 소수 인 때문에. 다시 인도 독립 기념 행사를 보러 가려면 몇 주 전에 가서 20 일을 기다려야 할 것 같습니다.

나는 가고 싶은 다른 날짜가 있고, 마찬가지로 목표 날짜 이전 (또는 운이 좋으면 같은 경우)까지의 날짜로 가야합니다.이 숫자는 소수입니다. 나는 참을성이 없어서 너무 기다리기를 원하지 않는다. 그래서 내가 사용할 수있는 날짜를 목표 날짜와 가장 가까운 곳에서 찾고 싶다.

목표 날짜를 가져와 타임머신에 입력해야하는 날짜를 알려주는 프로그램을 작성할 수 있습니까? 부품이 소수에 해당하는 지정된 날짜 이전 또는 가장 가까운 날짜입니다.

(이 문제를 해결하기 위해 우리는 독창적 인 그레고리력을 사용하고 있습니다. 즉, 사람들이 이전 율리우스 력을 사용하던 기간에도 현재 그레고리력을 사용한다는 의미입니다.)

입력

  • 날짜
    • 이상적으로, 현재 시대 (AD)의 모든 날짜; 실제로, 귀하의 언어 중 일부만 자연스럽게 처리 할 수있는 것은 무엇이든
    • 원하는 사람이 읽을 수있는 형식으로

산출

  • 입력 날짜와 가장 근접한 날짜이며 입력 날짜보다 작거나 같고 날짜 + 월 + 년이 소수입니다.
    • 원하는 사람이 읽을 수있는 형식으로

⁺ : 일, 월, 연도에서 "인간이 읽을 수있는"순서대로, 모든 철자가 표기 됨

테스트 사례

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

(질문에 도움을 주신 @Shaggy, @PeterTaylor 및 @Arnauld에게 감사합니다.)


출력에서 넌센스 시간을 갖는 것이 괜찮습니까? (예 Fri Jul 25 02:46:39 CEST 1947)
wastl

@wastl 예, 날짜 정보가 연속적인 고정 된 고정 길이 서브 스트링 인 경우 (예 : 해당 예에서는 아니오).
sundar-복 직원 모니카

답변:



4

자바 스크립트 (Node.js) , 94 바이트

카레 구문에서 3 개의 정수로 입력을 (year)(month)(day)받습니다. 하이픈으로 시작하는 하이픈으로 구분 된 문자열을 반환합니다.

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

온라인으로 사용해보십시오!

방법?

먼저 날짜를 JSON 형식 yyyy-mm-ddT00:00:00.000Z( ISO 8601 ) 으로 변환하고으로 나누고 'T'왼쪽 부분 만 유지 하고 앞에 하이픈을 추가하여을 제공합니다 -yyyy-mm-dd.

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

이 표현 지금 할 수있다 eval()'반대를 얻을 수 uated N 의 합의 년 + 월 + 일 .

n = eval(s)

헬퍼 함수 P () 를 사용하여 -n 이 소수 인지 테스트합니다 (이 경우 0 을 리턴 함 ). 그렇다면 s 를 반환 합니다 . 그렇지 않으면 전날부터 다시 시도합니다.

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

1
프라임 체크가 어떻게 작동하고 종료되는지 이해하는 것만으로 하루를 쉬는 것처럼 느낍니다. 좋은 골프!
sundar-복원 모니카

3

파이썬 (2) , 130 (127) 바이트

입력은 year, month, day입니다.

Kevin Cruijssen 덕분에 -3 바이트 .

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

온라인으로 사용해보십시오!


날짜 오브젝트를 입력으로 사용할 수 있으므로 3 바이트를 절약 할 수 있습니다 .
Kevin Cruijssen

1
@KevinCruijssen 감사합니다. 이것이 유효한 입력 형식 이라고 생각하십니까 ?
ovs

나는 왜 그렇지 않을지 알지 못하므로 다른 -4입니다. 그것에 대해 생각하지 않았다.
Kevin Cruijssen

2

자바 8, 144128 바이트

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

온라인으로 사용해보십시오.

java.time.LocalDate클래스는 이전에 비해 개선되었습니다 java.util.Date,하지만 왜 그랬는지 그들은 더 이상 그 이름을했습니다 ( getMonthValuegetDayOfMonth대신 getMonthgetDay) ..>.>

설명:

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

루비 , 94 바이트

온라인으로 사용해보십시오!

단일 날짜 입력을 가져와 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?}}

Ruby의 프라임 모듈을 사용합니다. 그것이 허용되지 않거나 찡그린 경우 2 바이트 이상이 혐오를 나타냅니다.


루비 , 97 바이트

온라인으로 사용해보십시오!

이 stackoverflow 응답 에서 소수 인 숫자 검사를 사용합니다 . 나는 이것이 어떻게 작동하는지 전혀 모른다. 마술처럼 보인다. 위와 동일한 입력 및 동일한 출력.

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

가져 오기 줄이 바이트 수에 포함되어 있으면 모듈을 사용하는 것이 좋습니다. 초기 d와 그 이후의 공간 주위에 패러 틴을 필요로하지 않는 것처럼 보이 if므로 첫 번째 답변에서 3 바이트를 제거하여 제거 할 수 있습니다. TIO 링크
sundar-복원 모니카

3
나는 마술 같은 혐오를 좋아한다. 일단 ?x*n !~ /^x?$|^(xx+?)\1+$/n이 소수인지 확인하고, n 'x 's 문자열을 만들고, 0 또는 1 x (소수가 아닌)인지 확인하고 일치하지 않는지 확인합니다. 2 개 이상의 x 자체 반복 (일치하는 ^(xxxxx)\1+$것은 n을 5로 나눌 수 있음을 의미 함). 그것은 우리를 위해 우리의 루핑을하기 위해 정규식 엔진의 역 추적을 남용합니다-훌륭하고 괴물이며 동물 희생이 발견에 관여했을 것입니다.
sundar-복 직원 모니카

괄호와 공간에 대한 좋은 장소! 감사.
IMP1

"마술"버전은 92 바이트로 수행 할 수 있습니다 ( 여기 참조) . 우선 순위를 확인하려는 합계가 3 이상 (최소 날짜 0001-01-01이 1 + 1 + 1 = 3이므로) 정규식의 일부를 제거하여 입력을 0으로 처리 할 수 ​​있습니다. 1. 제거하고 단순화하면 91 바이트 버전이 제공됩니다.
sundar-복원 모니카

흥미로운 접근법. 'month'대신 'mon'을 사용하여 2 바이트 저장
GB

2

루비 , 57 53 바이트

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

온라인으로 사용해보십시오!

내 생각이 아님-IMP1의 "혐오"에서 도난


독창적 인 아이디어 :

루비 , 59 바이트

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

온라인으로 사용해보십시오!


1
사용하는 것 8e4대신에 일을?
Kritixi Lithos 2016

예, 물론 작동합니다. 또한 9 또는 다른 작은 숫자를 사용하여 작동합니다. 실행하는 데 시간이 오래 걸립니다. 감사.
GB


2

F 번호, 134 133 바이트

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

sundar 덕분에 -1 바이트 .

온라인으로 사용해보십시오!

일, 월 및 연도를 합계하여 소수인지 확인하십시오. 그렇다면 해당 날짜를 반환하십시오. 그렇지 않으면 날짜를 1 일씩 줄이고 다시 시도하십시오.


1
당신은 서면으로 바이트를 저장할 수 있습니다 -1.0으로 -1.AddDays 호출에서.
sundar-복원 모니카

당신 말이 맞아요. 정말 이상합니다. 그러나 유용합니다. 감사.
Ciaran_McCarthy 2016 년

1

PowerShell , 105 90 바이트

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

온라인으로 사용해보십시오!

-13 바이트의 sundar 덕분입니다.

입력을 a DateTime 2018-06-20로 가져와에 저장합니다 $a. 그런 다음 우리는 for루프에 있습니다. 반복 할 때마다, 우리는 복용하고 $a -f같은 ormatted yyyy+MM+dd(즉, 우리가에있어 현재 날짜로 구분 +와 함께 추가 징후) |iex(유사에 eval), 문자열 곱에 있음을 1의 단항 번호를 형성하고, 사용하는 주요 검사 정규식 현재 날짜가 소수인지 확인합니다. 소수가 아니면 .AddDays(-1)하루를 거꾸로 돌아가 루프를 계속해야합니다. 프라임 인 경우 루프를 벗어나 $a암시 적 출력으로 파이프 라인에 배치 합니다.

결과 출력은 문화에 따라 다릅니다. 를 사용하는 TIO en-us에서 출력은 긴 형식으로 표시됩니다 Saturday, July 1, 1319 12:00:00 AM.


인수를 datetime 객체로 보내 몇 바이트를 절약 할 수 있습니다. 또한 정규식을 2보다 큰 합성물 과 일치 하도록 단순화 할 수 있습니다 (최소 날짜는 0001-01-01합계가 3이므로). 나는 이러한 변화에 균열을했다 여기 .
sundar-복 직원 모니카

(저는 powershell 초보자이며 링크 된 코드는 최소한으로 만 테스트되었으며 여기에서 모든 테스트 사례를 시도하지는 않았습니다.)
sundar-Reinstate Monica

@ sundar 그 입력에 대해 생각했지만 조금 "약간"인 것처럼 보였으므로 대신 문자열 입력을 사용했습니다. 정규식에 대한 팁을 주셔서 감사합니다. 어떻게 작동하는지 완전히 이해하지 못하기 때문에 웃을 때 고개를 끄덕입니다. 헤헤
AdmBorkBork 2018 년

1

배쉬 , 114 108 바이트

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

온라인으로 사용해보십시오!

내 첫 번째 배쉬 골프. 솔직히, 내 첫 번째 실제 bash 프로그램은 ... 여기서 원시 테스트를 수행했습니다 .

시간대 변경이있는 경우 때때로 실패 할 수 있지만 TIO는 UTC를 사용하므로 작동해야합니다.


첫 번째 줄의 "9"가 오타입니까? (입력에 공백이 없어야 할 수 있기 때문에) 따옴표와 그 주변의 따옴표를 제거하고 끝에 끝에 a를 추가 @$하면 작업 코드가 110 바이트가 됩니다.
sundar-복원 모니카

@sundar 일광 절약 시간제에 문제가 있다고 생각했지만 내일 다시 확인하겠습니다
wastl

1

C (gcc) , 167 바이트

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

온라인으로 사용해보십시오!

개요

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

프라임 방지 점검 기능. 처리해야 할 가장 유효한 연도는 0001-01-01이므로 걱정할 필요가있는 가장 낮은 숫자는 3이므로 n == 2 또는 n <2에 대한 특수 사례 검사가 제거됩니다. n이 소수 가 아닌 경우 r은 정확한 값으로 설정됩니다 . r은 전역을 유지하므로 반환하지 않아도되므로 2 바이트가 절약됩니다 ( 전역을 검사하기 위해 i=n;vs ,r를 반환 ). 함수 호출자가 i를 1로 설정하여 다른 2 바이트를 저장합니다.

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

우리는 날짜를 세 개의 개별 정수로 취하고 y + m + d가 소수가 될 때까지 메인 루프를 시작합니다. 그런 다음 함수의 고기에옵니다.

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

평가 순서가 지정되지 않은 경우 윤년 검사에서 문자열 색인으로 m과 y를 모두 사용하는 것이 좋지 않을 수 있습니다. 운 좋게도, 우리는 m == 2 인 경우 윤년 만 점검합니다. 이것은 m과 y를 변경하는 것과 동시에 일어날 수 없습니다. 1 월부터 12 월까지만 발생하기 때문에 윤년 점검은 결코 평가 순서.

마지막으로 결과가 STDOUT에 인쇄됩니다.

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

0

C 번호 - 281 239 232 숯불

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

언 골프 :

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

코드의 효율성은 떨어지지 만 작게 만들었습니다. 프라임 루프는 이제 제곱근이 아닌 정수로 올라갑니다. 또한 모든 짝수를 처리합니다.


아마도 제거 할 수 있습니다 public. 또한 날짜 입력을 호출 매개 변수로 얻는 것이 허용되지 않는 것처럼 보이 Main(string[]a)DateTime.Parse(a[0])
므로

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.