언더로드 번호의 최단 표현


13

맛 텍스트

스택 기반 esolang Underload 는 기능적 프로그래밍과 관련이 있습니다. 그중 하나는 숫자 데이터 유형을 처리하는 것입니다. 람다 미적분과 같이 N 번 동작을 수행하는 함수로 자연수 N을 나타냅니다.

일을 간단하게하기 위해, 우리는 다음과 같은 언더로드 명령의 하위 집합 만 고려할 것입니다.

  • : -이 명령은 스택의 최상위 항목을 복제합니다.
  • * -이 명령은 스택의 상위 2 개 항목을 단일 항목으로 연결합니다.

우리는 정의 저 부하 번호를 N (A)의 문자열로 :하고 *, 실행되는 스택의 상위 항목을 소비하고, 해당 항목이 함께 연결된 N의 복사본을 생성한다. 몇 가지 예 :

  • 언더로드 숫자 0, -1, 1/2, π는 없습니다.
  • 빈 문자열 은 스택을 건드리지 않기 때문에 Underload 숫자 1입니다.
  • :*Underload 숫자 2는 맨 위 항목을 복제 한 다음 두 사본을 단일 항목으로 연결하기 때문입니다. (A):*= (A)(A)*= (AA).
  • ::**Underload 숫자 3 : (A)::**= (A)(A):**= (A)(AA)*= (AAA)입니다.
  • :::*** Underload 숫자 4입니다.
  • :*:*또한 Underload 숫자 4 : (A):*:*= (AA):*= (AA)(AA)*= (AAAA)입니다.

일반적으로,이 경우 해당를 찾을 수 MN저 부하 숫자 M과 N은 다음 :N*숫자 N + 1이며, MN숫자 M × N이다.

도전

당신의 임무는 입력 으로 문자열에 대한 Underload 숫자가장 짧은 표현 을 생성하는 가장 짧은 프로그램 (STDIN의 입력 입력) 또는 함수 (인수를 통한 입력 입력)를 작성하는 것 입니다. 즉, 입력이 양의 자연수 N> 1 인 경우 문자의 길이가 다른 모든 언더로드 숫자 N의 길이보다 작거나 같은 언더로드 숫자 N을 생성해야합니다.

샘플 입력 및 출력 : ( "Input- OUTPUT.")

  • 1- .
  • 2- :*.
  • 5- ::*:**(2 × 2 + 1).
  • 7- ::*::***(2 × 3 + 1) 또는 :::**:**(3 × 2 + 1).
  • 33- ::*:*:*:*:**(2 × 2 × 2 × 2 × 2 + 1).
  • 49- ::*:*:*:*::***(16x3 + 1, 길이 14) ::*::***::*::***(7x7, 길이 16)는 아닙니다 .

입력이 양수가 아닌 경우 오류를 반환하거나 정의되지 않은 동작을 생성하거나 종료하지 못할 수도 있습니다. 답변을 찾는 제출 방법에 대한 설명을 부탁드립니다.

표준 허점 제한이 적용되지 않습니다 : 불필요한 입력을, 어떤 웹 요청, 출력 / 반환 값은 정확하게 대답하고 아닌 무한 랜덤 스트림 없어야합니다 :*등,


@Geobits 나는 실행 시간에 대해 아무 말도하지 않았으므로 결국 정답을 줄 것이라고 증명할 수 있다면 좋다.
algorithmshark

2
이 문제는 추가 체인과 관련이 있습니다. 구체적으로는, 입력에 대한 정답의 길이는 x이고 2*A117498(x)여기서 A117498는 첨가 연쇄를 찾기위한 이진 및 계수 방법의 최적의 조합을 제공한다.
피터 테일러

답변:


4

GolfScript ( 61 60 55 54 53 자)

~:X'']({:A{.'.+'\*A{2$+}%~}%}*{,}${1\~X=}?{44/'*:'=}%

이것은 이전 버전보다 까다 롭지 않고 약간 다른 접근법을 취하지 만 여전히 무차별입니다. 우리 ':'X*'*'X*+는 이것이 후보 솔루션 이라는 것을 알고 있으므로, 균형이 잘 잡힌 모든 문자열을 그 길이까지 생성하고 가장 짧은 것을 취하면 올바른 것을 찾을 수 있습니다.

# Evaluate input and store the target number in X
~:X
# Seed the generator with the empty string
'']
# X times...
({
    # Store the array of strings so far into A
    :A
    # Generate A' by mapping each element
    {
        # Dup: this leaves an untouched copy of the current string
        .
        # Wrap the duplicate in .+
        '.+'\*
        # For each element in A, generate that element suffixed with the current string
        A{2$+}%~
    }%
}*
# Order by length
{,}$
# Find the first element which evaluates to X
{1\~X=}?
# tr .+ :*
{44/'*:'=}%

하워드 덕분에 몇 가지 1 문자 조정을 훔친 솔루션이 있습니다.


Haha, 3을 입력하면 웹 인터프리터에서 실행하는 데 3 초 이상 걸립니다. 최고의 골프.
algorithmshark

@algorithmshark, 중복 제거 지점으로 속도를 크게 높일 수 있습니다. .&내부 루프 바로 뒤에 삽입하십시오 (예 : ~}%와 사이 }*.
Peter Taylor

4

GolfScript ( 54 53 자)

이것은 Howard의 정신에 맞는 접근법입니다 (올바른 값으로 평가되는 것을 찾기 위해 후보 문자열을 통해 무차별적인 힘이 아닌 정확한 값으로 평가하고 가장 짧은 문자열을 선택하는 문자열을 작성하십시오)이지만 생각과는 완전히 다릅니다. 별도의 답변에 속합니다.

~.''':*':s@,{):x,2>{:^~$x^/~$+{s\*}x^%*}%{,}$0=}/]((=

인터프리터의 버기 버전을 실행하기 때문에 온라인 데모를 사용할 수 없습니다.

# Let <N> denote the string which evaluates to N
# We want to enter the main loop with three values on the stack: <0> <1> <2>
# However, we'll never use <0>, so we can actually replace that with any value at all.
# Getting the input from underneath 3 items would normally use two stack manipulations.
# Trick: let's use the input value for <0>! (This gives a further bonus later).
# NB We store the value of <2> in the variable s
~.''':*':s@
# for x=1 to input_value ...
,{):x
    # for ^=2 to x-1 ...
    ,2>{:^
        # Use negative stack offsets to index the stack from the start
        # I.e. -1$ gets the first item on the stack, which is <0>
        # -2$ gets the second item on the stack, which is <1>
        # In general, val~$ gets <val>
        ~$x^/~$+
        # We have the string <^><x / ^> on the stack.
        # Increment it (x % ^) times to get a candidate <x>.
        {s\*}x^%*
    }%
    # Select a shortest string.
    {,}$0=
}/
# Group the stack into one array and select the appropriate offset,
# reusing that hacky <0> substitute for the offset.
]((=

대체하여 하나를 면도 할 수있을 것 3+으로 )(사실 이용 []0=하면 해당하는 것은 아니었다없는 경우 스택에 잎 아무것도) []2>오류로 리드를.
피터 테일러

[]2>[]오류없이 산출 합니다.
Howard

@Howard, ah, golfscript.apphb.com 이전 버전을 실행 해야합니다 . 그러나 교체로 인해 input에 대한 잘못된 출력이 발생하기 때문에 내가 틀렸다는 것이 밝혀졌습니다 '1'.
피터 테일러

((=대신에 고칠 수 있습니다 -1=.
Howard

그리고 golfscript.apphb.com은 실제로 이전 버전을 실행하지만 중첩 루프 예제 는 작동하지 않습니다.
Howard

4

파이썬 2.7 - 87 84 92

u=lambda n:n>1and min([u(i)+u(n/i)for i in range(2,n)if n%i<1]+[':'+u(n-1)+'*'],key=len)or''

설명 :
이것은 매우 간단한 해결책입니다. n의 가능한 모든 표현을 두 숫자의 곱 또는로 재귀 적으로 테스트 :(n-1)*한 다음 최소 길이 솔루션을 찾습니다. range (2, n)은 재귀가 깊이를 제한하기 위해 필요하며 n <2는 기본 사례를 제공합니다.

참고 :
i와 n / i는 n의 두 가지 요소입니다. ''가 false로 평가되므로 ... 및 ... 또는 ...의 경우 ... if ... else ...가 작동하지 않습니다. 최소 문자열 수는 가장 짧은 문자열 중 하나를 제공합니다. Python 2.7은 // 대신 /를 사용하여 1 개의 문자를 저장합니다.

편집 : 기본 사례를 표현식의 뒤로 이동하여 ... 및 ... 또는 ...을 사용하고 몇 칸을 면도 할 수있었습니다.

테스트 사례 :

u(1)
''
u(5)
'::*:**'
u(49)
'::*:*:*:*::***'

1
" 문자열의 분은 짧은 문자열 중 하나 준다 "는 옵션 인수를 제공하지 않는 사실이 아니다 key=len. 사 전적으로 가장 빠른 문자열을 제공합니다. ( ). 때문에 '*' < ':'이 방법 당신은 2의 거듭 제곱을 포함하는 솔루션을 향해 편견을 가지고 있지만, 그들은 항상 짧은 것을?
피터 테일러

1
답 : 실제로 편향은 더 복잡하지만 항상 정답을 제공하는 것은 아닙니다. 가장 작은 반례는입니다 u(33). 사전 식으로 정렬하면 14 자 ::**::*::*:***이지만, 길이별로 정렬하면 12 자입니다.::*:*:*:*:**
Peter Taylor

1
파이썬 문자열 비교에 대해서는 전혀 몰랐습니다. 내 답변을 업데이트했습니다.
isaacg

3

GolfScript, 63 58 56 자

~n./\{:v~[':*'1$*v,,2>{v,\%!},{.v=v,@/v=+}/]{,}$0=]}*-2=

코드는 STDIN에서 입력을 받아 결과를 인쇄합니다.

예 :

> 49
:::**:*:*:*:**

> 1234
::::*:*:*:**:*:*:**::**::***

온라인에서 자신의 사례를 테스트 할 수 있습니다 .


와우, 나는 팩토링 기반 접근 방식이 무차별 접근 방식보다 훨씬 길 것이라고 생각했습니다.
피터 테일러

@PeterTaylor 나도 그렇게 생각했지만 그것은 사실이 아닙니다. 게다가, 나의 무차별 대입 솔루션은 당신보다 약간 길었다 ;-)
Howard

각 부분이 무엇을하는지 설명해 주시겠습니까? :x(=비트 까지만 후속 조치를 취할 수 있습니다 . 또한 합리적인 시간에 49를 실행할 수있는 +1입니다.
algorithmshark

@algorithmshark 나는 여전히 솔루션을 개발 중이므로 여전히 많이 변경 될 수 있습니다. 주로 부분은 x,2>{x\%!},모두 사실 약수를 제공 x, {.v=x@/v=+}/다음의 솔루션을 연결 d하고 x/d모든 제수를 위해 d. {,}$길이별로 정렬하고 0=가장 짧은 것 (초기 :(x-1)*경우)을 취합니다 .
Howard

2

Brachylog 2 , 30 (어쩌면 26) 바이트, 언어 날짜 도전

다음은 현재 Brachylog 2 구현에서 작동하고 현재 구현에 문자열 처리에 문제가 있기 때문에 문자 코드 목록을 반환하는 함수입니다.

∧.l∧?{ḋp~c×ᵐ{-₁↰₁:[42,58]c↻}ᵐc}

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

언어는 여전히 매우 새롭습니다. 여기의 26 바이트 (그것은 또한 더 적은 효율적) 미래에있을 것입니다 어쩌면 사양에 따라 작동해야 프로그램의 버전이 있지만, 일부 구현되어 있지 않은 기능을 사용하며, 따라서 아직 유효하지 않습니다,하지만 :

{ḋp~c×ᵐ{-₁↰₁:"*:"c↻}ᵐc}ᶠlᵒh

설명

∧.l∧?{ḋp~c×ᵐ{-₁↰₁:[42,58]c↻}ᵐc}
∧.l∧?                            Evaluation hint: try shortest outputs first
     {                        }  Define an inner function
      ḋ                          Prime factor decomposition of the input
       p                         Find a permutation
        ~c                       Find an inverse concatenation (i.e. partition)
          ×ᵐ                     Take the product of each set inside the partition
      ḋp~c×ᵐ                     Find a decomposition into factors ≥ 2
            {              }ᵐ    For each of those factors:
             -₁                  Decrement it
               ↰₁                Call the inner function recursively
                 :[42,58]c       Append "*:" (as character codes)
                          ↻      Move the last element to the start
                             c   Append the results together

기본 아이디어는 상당히 간단합니다. 우리는 숫자를 (1 개 이상의) 요소로 분해하는 것 (필수 요소는 아니지만 1 요소는 허용되지 않음)과 각 요소를 1 + (재귀에서 얻은 표현)로 표현합니다. 요구). 이것은 숫자의 가능한 모든 Underload 표현을 검색 할 수 있도록 보장합니다 (2 개 이상의 숫자를 곱하여 곱셈 단계 "연속 두 번"을 적용하고 곱셈 단계를 곱셈 단계로 분리하여 증분 단계를 연속으로 두 번 적용 할 수 있습니다. 하나의 숫자 만 함께). 1을 소수로 분해하면 빈 목록이 생성되므로 0을 곱하는 곱셈 단계로 구성하기 때문에 명확한 기본 사례는 필요하지 않습니다.

문제의 "가장 짧은"부분을 해결하면서 내가 준 평가 순서 힌트 (최종 결과의 크기 측면에서 가장 짧은 답변을 가장 오래 생성 함) 때문에 프로그램은 상당히 비효율적입니다. 실제로 프로그램을 빠르게 완성시킵니다 (보다 유용한 힌트는 "각 재귀 단계에서 가장 짧은 답만 생성하는 것"이지만 더 많은 바이트가 필요합니다 ...). 또한 ḋp~c×ᵐ곱하기 파티션을 여러 번 생성하여 프로그램이 많은 중복 작업을 수행 할 수 있습니다.


0

J-81 자

후손에게는 이것이 J에서 할 수있는 최선이었습니다.

_2{::(0&(][,0{<@;"1@({~#(#~]-:"1<.)@(],.%)2}.i.@#)(/:#&>)@,':'<@,'*',~>@{:),~)&a:

우리 는 0 (사용하지 않음)과 1을 나타내는 두 개의 빈 문자열 ( ,~a:)로 시작하여 결과 목록을 만든 다음 그다음 동사를 반복합니다 (후크, 기차 및 &)를 사용하여 다음 숫자의 가장 짧은 표현을 추가합니다.

우리가 반복하는 실제 동사는 목록의 길이를 우리가 운영하는 숫자의 지표로 사용합니다. 먼저이 숫자를 인수 쌍 ( #(#~]-:"1<.)@(],.%)2}.i.@#) 으로 인수 화 하고 배열 ( {~) 에서 각 쌍을 가져옵니다 . 각 쌍 (숫자가 소수이면 0이 될 수 있음)을 단일 문자열 ( <@;"1) 로 바꿉니다 .

그런 다음 이전 목록의 결과를 :and 로 괄호로 묶고이 *목록을 길이 ( (/:#&>))로 정렬합니다 . 마지막으로이 목록에서 첫 번째 결과 ( 0{)를 가져 와서 기본 배열의 끝에 추가합니다 ( [,). 루프가 반복되면 0부터 시작하여 입력보다 길이가 2 더 많은 목록이 있습니다. 따라서 반환해야 할 것은 다음에서 마지막 문자열 ( _2{::)입니다.

   un =: _2{::(0&(][,0{<@;"1@({~#(#~]-:"1<.)@(],.%)2}.i.@#)(/:#&>)@,':'<@,'*',~>@{:),~)&a:
   un 49
::*:*:*:*::***
   un 1234
:*::*:*:*::*::***::*::*:****
   un 10010
:*::*:*::***::*:*:*:*:*:*:*::***
   2 * (1 + 3 * 2^2) * (1 + 3 * 2^7)
10010
   6!:2 'un 10010'   NB. time in seconds
19.5539

0

젤리 , 33 바이트, 언어 날짜 도전 과제

ÆḌḊµ⁹÷Ñ;Ñð€
’ß”:;;”*W;ÇLÞḢµ“”>1$?

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

간단한 무차별 대입 솔루션.

설명

주요 프로그램

’ß”:;;”*W;ÇLÞḢµ“”>1$?
              µ  >1$?  If input is greater than 1, then:
’ß                       Run recursively on the input - 1
  ”:;                    Prepend a colon
     ;”*                 Append an asterisk
        W;               Cons to:
          Ç                the result of the helper, on {the original input}
           LÞ            Sort by length
             Ḣ           Take the first (i.e. shortest) result
               “”      Otherwise, return an empty string

기본 프로그램은 도우미 함수를 사용하여 곱셈을 통해 값을 생성하는 모든 가능한 방법을 열거 한 다음 더하여 값을 생성하려고 시도하고 가장 짧은 가능성을 반환합니다. 또한 기본 사례 (의 입력 1) 도 처리합니다 .

도우미 기능

ÆḌḊµ⁹÷Ñ;Ñð€
ÆḌ µ     ð€            For all proper factors of the input
  Ḋ                    except the first (i.e. 1):
    ⁹÷                   Divide it into the input;
      Ñ                  Run the main program on it;
       ;                 Append the result of:
        Ñ                  the main program run on {the factor}

도우미 함수는 입력을 두 숫자의 곱으로 표현하는 모든 가능한 방법을 시도하고 가장 짧은 표현을 얻기 위해 주 프로그램을 상호 재귀 적으로 호출합니다.


0

GNU 프롤로그, 96 바이트

v(N)-->{N#=1};{N#=A*B,A#<B,B#<N},v(A),v(B);{N#=M+1},":",v(M),"*".
s(N,S):-length(S,_),v(N,S,[]).

첫 번째 줄은 Underload 평가를 구현하고 반대 방향으로 작동하는 문법입니다 (실제로 A#<B제약 조건 으로 인해 순방향으로 작동하지 않습니다 A#<N. 두 가지 방식으로 작동하는 느린 프로그램의 경우 이를 변경하십시오 ). 두 번째 줄은 함수와 같은 술어 s(이 프로그램에 대한 솔루션으로 구현되는 함수)를 정의합니다.이 술어 는 입력으로 주어진 수로 평가되는 가장 짧은 문자열을 찾습니다 (이것은 비교적 간단한 작업에 대한 자세한 장황하지만 그것은 당신을위한 프롤로그입니다…).

프로그램은 문법을 문법으로, 그리고 프롤로그 구문을 직접적으로 변환한다는 점을 감안할 때 매우 자명하다. 의 정의는 v것을 말한다 N빈 문자열 1, 또는 N이다 A× B(함께 A미만 B미만 N) 및 문자열의 연결입니다 v(A)v(B), 또는 N이다 M1 +와 문자열이됩니다 :와 연결 v(M)와 연결 *. 두 번째 줄은 조금 미묘합니다.length(S,_) "S는 약간의 길이를 가짐"을 의미하지만 이것을 라인의 첫 번째 것으로 지정하면 가장 짧은 길이를 먼저 확인해야한다는 Prolog 구현의 힌트 역할을합니다 (즉, 반환 값에 대해 가능한 가장 짧은 길이를 얻습니다) .

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