(거의) 원하는 숫자로 방정식을 풉니 다


27

+=-하나 이상의 문자 가 있는 문자열 =이 제공되면 수학 기호가 충족되도록 모든 기호 사이와 시작 및 끝 사이에 양의 정수를 삽입하십시오.

예를 들어, 입력이 주어지면

+-=-=

이처럼 양의 정수 A에서 F까지 삽입해야합니다.

A+B-C=D-E=F

이러한 방정식은 모두, 즉 만족하는지 A + B - CD - E그리고 F모두 동일한 번호이다.

방정식이 해결되는 한, 양의 정수 세트가 사용될 수 있기 때문에이를 수행 할 수있는 많은 방법이 있습니다. 여기의 각 줄은 입력 가능한 유효한 출력입니다 +-=-=.

2+3-4=6-5=1
1+1-1=2-1=1
4+2-4=4-2=2
100+1-10=182-91=91
89+231-77=1024-781=243

식의 값은 삽입 된 숫자와 같은 양의 정수일 필요는 없습니다. 예를 들어, 주어진 입력 -=-에서 출력 1-10=8-17(evals to -9) 및 10-1=17-8(evals to 9)은 모두 동일합니다. 물론 같은 입력 =만 가능하므로 식과 같이 음수를 입력 하는 것은 불가능합니다 5=5.

또한 0은 양의 정수가 아닙니다.

바이트 단위의 가장 짧은 코드가 이깁니다.

숫자를 문자열에 직접 삽입하는 대신 목록으로 출력 할 수 있습니다. 문자열을 출력하면 기호와 숫자를 구분하는 공백이있을 수 있습니다. 따라서 입력의 +-=-=경우 출력

2, 3, 4, 6, 5, 1

또는

2 + 3 - 4 = 6 - 5 = 1

출력과 동일

2+3-4=6-5=1

테스트 사례

Input | One Possible Output
= | 1=1
== | 2=2=2
+= | 1+3=4
=+ | 2=1+1
-= | 30-10=20
=- | 1=2-1
=-= | 3=7-4=3
=+= | 2=1+1=2
=== | 100=100=100=100
+=- | 3+2=7-2
-=+ | 7-2=3+2
+=+ | 3+3=3+3
-=- | 1-10=8-17
--= | 60-1-1=58
++= | 60+1+1=62
-+= | 60-9+1=52
+-= | 60+9-1=68
+-=-= | 2+3-4=6-5=1
--=-- | 2-1-1=2-1-1
==-== | 47=47=50-3=47=47
=++=+-=-+=--= | 3=1+1+1=3+1-1=1-1+3=5-1-1=3
+--++-=-+-+- | 35+10-16-29+20+107-1000=5-4+3-2+1-876
====== | 8=8=8=8=8=8=8


공식의 길이에 상한을 가정 할 수 있습니까?
xnor

2
@xnor 입력이 2 ^ 16 자 미만인 것으로 가정 할 수 있습니다.
Calvin 's Hobbies

답변:


16

망막 , 58 바이트

[-+]
$&1
\B((\+1)|(-1))*
$._$*1$#3$*1$#2$*_$&
+`1_

1+
$.&

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

동일한 바이트 수의 대체 솔루션 :

((\+)|(-))*
$._$*1$#3$*1$#2$*_$&
+`1_

([+-])1*
$+1
1+
$.&

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

설명

기본 아이디어는 모든 +s와 -s를 단순 +1하고 -1연산 으로 바꾸고 모든 방정식이 작동하도록 충분히 많은 수를 추가하는 것입니다. 방정식을 일치시키기 위해 각 숫자에 동일한 숫자를 붙이고 각 숫자를 하나씩 줄인 후 그 숫자를 하나씩 +1증가시킬 수 -1있습니다. 우리는 단항 수로 작업 할 것이기 때문에, 첫 번째 숫자는 첫 번째 숫자가 충분히 커야 1 회 정도 줄일 수 있다는 것입니다.

[-+]
$&1

우리는을 삽입하여 시작 1각 후 -또는 +.

\B((\+1)|(-1))*
$._$*1$#3$*1$#2$*_$&

\B보장하지만이 경기는 입력의 시작 부분 중 하나, 또는하는 사이 =+-, 즉 우리가 표현의 선두 번호를 삽입 할 모든 위치를. ((\+1)|(-1))*부분은 단순히의 수를 계산 +1s와 -1의 그룹 23각각을. 이제 대체 문자열을 세분화하십시오.

$._$*1   # For each character in the current string, insert a 1. This is
         # an offset which is the same for each expression and is guaranteed
         # to be large enough that all subsequent +1s can be cancelled.
$#3$*1   # For each -1, insert a 1.
$#2$*_   # For each +1, insert a _.
$&       # Re-insert the string of +1s and -1s.
+`1_

s 1_에서 필요한 취소를 적용하여 문자열에서 반복적으로 삭제 합니다 +1.

1+
$.&

마지막으로 1s의 모든 문자열을 길이로 바꾸어 단항에서 10 진수로 변환합니다.


8

파이썬 2 , 76 바이트

lambda e:sum([[len(e+s)-2*s.count('+')]+[1]*len(s)for s in e.split('=')],[])

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


3
설명을 추가 할 수 있습니까?
Calvin 's Hobbies

1
@HelkaHomba 아이디어는 매우 간단합니다. 먼저 입력 분할의 각 청크를 등호로 나눕니다. 각 청크의 첫 번째 숫자를 선택하십시오 eqtn_len + plus_signs + minus_signs - 2 * plus_signs = eqtn_len + minus_signs - plus_signs. 그런 다음 청크의 다른 모든 숫자는 1이므로 청크의 총계는 다음과 같습니다 eqtn_len + minus_signs - plus_signs - minus_signs + plus_signs = eqtn_len. 방정식 길이는 양수 여야하므로 모든 것이 잘됩니다.
FryAmTheEggman

6

파이썬 2 199 179 178 172 162 158 156 152 151 바이트

너무 길었지만 솔루션을 쉽게 만들 수있었습니다.

from itertools import*
i=input()
k='%s'
s=k+k.join(i)+k
for p in product(*[range(1,65537)]*-~len(i)):
    if eval((s%p).replace('=','==')):print s%p;break

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

이것은 해결책을 찾을 때까지 모든 가능성을 시도합니다. 프로그램이 매우 느립니다. 또한 모든 반복마다 문자열 교체를 수행합니다. "172"편집은 작은 범위에서 시작하지 않고 최대 값에서 시작하므로 속도가 크게 느려졌습니다. 예를 들어, 입력 -=또는 =+솔루션에 도달하기 전에 2 개 ** 32 시도를 시도해야합니다.

프로그램 속도를 높이려면 편집 히스토리에서 178 바이트의 버전을 사용하십시오.


하지 않습니다 rangepython2 즉시 목록으로 전체 범위를 만들? IIRC xrange는 게으른 로딩 버전이라고 생각하기 때문에 대신 대신 사용하여 속도를 높일 수 있습니다 (Python3은 lazy를 기본값으로 사용합니다 range)
Delioth

1
@Delioth 다른 바이트를 사용합니다. 목표는 바이트 를 제거 하는 것입니다 . 또한 대부분의 속도 저하는 목록의 생성이 아니라 반복 횟수에서 발생하기 때문에 실제로 많은 속도 향상을 제공하지는 않습니다. 단 한 번만 발생합니다. 나는 달렸고 print range(1,65537)0.034 초에 완료되었습니다.
mbomb007

물론, 너무 오래 걸리는 것에 대해 걱정하면서 "정확히 동일한 방법론으로 속도를 높일 수 있습니다." 메모리 스 래싱으로 인해 속도가 크게 저하 될 수 있습니다. 또한, 당신은 설정하지 않음으로써 일부 바이트 (어쩌면 유일한 1)을 줄일 수 l=...있지만,에 그 권리를 넣어 product(range(...),repeat=len(s)+1). 괄호가 필요한 경우 1 바이트 만 저장합니다 (\ n)
Delioth

@Delioth 괄호가 필요하더라도 괄호 가 필요없는 대신 len(s)+1사용할 수 있습니다 -~len(s).
mbomb007

아 맞아 나는 항상 비트 단위 연산과 트릭을 잊어 버린다-프론트 엔드에서 작업하는 자바 스크립트가 파이썬 전문 지식을 사용하고 있어야합니다!
Delioth

5

자바 스크립트 (ES6), 92 82 바이트

@xnor의 트릭으로 8 바이트 골프

let f =
x=>x.split`=`.map(q=>(x+q).length-2*~-q.split`+`.length+[...q,''].join(1)).join`=`
<input oninput="if(/^[+=-]+$/.test(value))O.innerHTML=f(value)" value="="><br>
<pre id=O>1=1</pre>

여기서 트릭은 1+또는 뒤에 -마침표 를 삽입 한 다음 각 표현식 앞에 표현식을 입력 길이와 같은 숫자로 묶는 것입니다. 이렇게하면 숫자가 항상 양수임을 보장 할 수 있습니다. =문자열 에는 항상 최소 1 이 있으므로 +s의 수는 문자열의 길이에 도달 할 수 없으므로 나머지는 항상 적어도 1입니다. +위의 스 니펫에 임의의 수의 s를 입력하여이를 확인할 수 있습니다 .


5

파이썬 2 , 120 119 바이트

mbomb007 덕분에 -1 바이트

a=['1'+(n and('1'.join(n)+'1'))for n in input().split('=')]
print'='.join(`max(map(eval,a))-eval(c)+1`+c[1:]for c in a)

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인

먼저 1모든 위치에 삽입 하여 가장 높은 값을 확인한 다음 모든 방정식에서 오프셋으로 추가합니다. 음수를 더할 수 없으므로 최소 결과는 +식에있는 의 양으로 만 주어 +집니다.


몇 개의 공백을 제거 할 수 있습니다.
mbomb007

5

GNU 프롤로그, 156 바이트

x(L,R,V)-->{E#>0},({L=[E|R],E=V};x(L,[E|R],X),("+",{V#=X+E};"-",{V#=X-E})).
q(L,R,V)-->x(L,T,V),({T=R};"=",q(T,R,V)).
s(Q,L):-q(L,[],_,Q,[]),fd_labeling(L).

설명

우리는 풀어야 할 방정식이 많으므로 실제 방정식 솔버를 사용하지 않는 이유는 무엇입니까?

x기본적으로 형식의 방정식에 대한 방정식 평가자입니다 +-+. 방정식 자체 외에도 두 개의 추가 인수 ( L,R방정식 값을 포함 하는 차이 목록 및 V방정식이 평가 하는 값 )가 있습니다. 프롤로그에서 평소와 같이, 당신이 지정할 수 있습니다 예를 들어, (어떤 식 으로든 내내 사용할 수있는 V과를 얻을 수 L,R지정 L,R과를 얻을 V, 모두를 지정하고 값이 올바른지 확인하거나하는 경우 적절한 제약 모두에 게재됩니다 둘 다 지정하지 않는 VL,R). "현재 요소"의를 L,R이름 E, 우리는 또한 주장이 포함E질문에 양수를 사용해야하므로 0보다 큽니다. 이 함수는 원하는 것보다 약간 더 장황합니다. 예를 들어 [E|R]목록은 오른쪽 연관이지만 더하기와 빼기는 왼쪽 연관이기 때문에 패턴 일치 / 일치하지 않음을 두 번 작성해야 했습니다. 안타깝게도 fd_labeling작동하려면 셀 목록에서 왼쪽 연관 목록 유형을 발명하는 대신 실제 목록을 사용해야합니다 .

q은 (와) 비슷 x하지만 포함 =합니다. 기본적으로 그냥 호출 x하고 재귀 적 으로 호출합니다 . 또한 차이 목록의 작동 방식을 매우 명확하게 보여 두 개의 차이 목록 L,TT,R하나의 차이 목록으로 연결할 수 있음을 보여줍니다 L,R. 기본 아이디어는 차이 목록이 인수를 사용하고 목록 자체가 앞에 붙은 RL을 반환하는 부분 함수라는 R것입니다. 따라서 한 차이 목록의 인수와 다른 차이 목록의 반환 값을 식별하여 함수를 구성하고 목록을 연결할 수 있습니다.

마지막으로, s문제의 작업을 실제로 해결하는 기능인 인은 q인수를 사용 하여 호출하는 래퍼 함수입니다 . 우리 []는 인수 로 제공하여 차이 목록을 일반 목록으로 변환하고 fd_labeling우리가 만든 방정식에 대한 해를 찾는 데 사용 합니다. (기본적으로 값을 다른 것으로 설정할 이유가 없으면 값을 1로 설정하는 것을 좋아합니다. 그러나 구성 할 수 있습니다. value_method(random)예를 들어 1을 어디에나 배치하는 것보다 더 "흥미로운"솔루션을 제공하며 여전히 매우 빠릅니다. )

샘플 출력

작성된 프로그램으로 :

| ?- s("=++=+-=-+=--=", V).

V = [3,1,1,1,3,1,1,3,1,1,5,1,1,3] ?

프로그램을 조금 더 길게 추가 value_method(random)하면 결과가 달라 지지만 다음과 같이 보입니다.

| ?- s("=++=+-=-+=--=", V).

V = [68,6,12,50,85,114,131,45,3,26,71,1,2,68] ? 

두 경우 모두 ?출력의 끝에는 둘 이상의 솔루션이있을 수 있습니다. (물론,이 경우, 우리는가 있다는 것을 알고 많은 개 이상의 솔루션!)


4

수학, 116 바이트

Join@@(Prepend[#^2,1-Min[Tr/@c]+Tr@#]&/@(c=Characters@StringSplit["0"<>#<>"0","="]/."+"->-1/."-"->1/."0"->Nothing))&

문자열을 입력으로 사용하고 양의 정수 목록을 리턴하는 순수 함수. 기본 전략 : 우리는 1을 더하고 1을 빼고 모든 식을 같게 만들기 위해 각 식의 초기 숫자를 선택합니다.

c=Characters@StringSplit[#,"="]/."+"->-1/."-"->1모든 등호 기호의 입력 문자열을 분할 것, 각을 대체 +하여 -1-에 의해 1. 그러나 시작 또는 끝에 등호가 있으면 무시됩니다. 따라서 각 끝에 새 문자를 인위적으로 추가하고 ( "0"<>#<>"0") 문자열 분리가 완료된 후 사라지게합니다 ( /."0"->Nothing).

각 하위 목록의 총계는 이제 각 식을 동일하게 만들기 위해 +s 및 -s 앞에 넣을 수있는 정수 와 같습니다. 1-Min[Tr/@c]각 합계에 더하여 모두 양수로 만들 수있는 가장 작은 정수입니다. 따라서 Prepend[#^2,1-Min[Tr/@c]+Tr@#]&각 하위 목록을 가져와 ( ^2모든 항목을로 바꿉니다 1)이 가장 작은 보상 정수만큼 이동 된 총수를 앞에 추가합니다. 결과 목록은 Join출력을 생성하기 위해 함께 묶입니다.


3

루비, 76

->s{(?1+s.gsub(/./){|a|a+?1}).split(?=).map{|e|e[0]="#{5**8-eval(e)}";e}*?=}

5**8골프의 이유로 표현의 목표 값은 마이너스 1로 고정됩니다 ! 원래는 s.size+1마이너스 1 을 사용하고있었습니다 .

테스트 프로그램에서 언 골프

f=->s{(?1+s.gsub(/./){|a|a+?1}).           #add a 1 at the beginning and after every symbol
       split(?=).                          #split into an array of expressions at = signs
       map{|e|                             #for each expression string
         e[0]="#{5**8-eval(e)}";e          #change the first number to 5**8-eval(e)
       }*?=                                #and rejoin the strings
}


puts f["="] 
puts f["=="] 
puts f["+="] 
puts f["=+"]
puts f["-="]
puts f["=-"]
puts f["=-="]
puts f["=+="]
puts f["==="]
puts f["+=-"]
puts f["-=+"]
puts f["+=+"]
puts f["-=-"]
puts f["--="]
puts f["++="]
puts f["-+="]
puts f["+-="]
puts f["+-=-="]
puts f["--=--"]
puts f["==-=="]
puts f["=++=+-=-+=--="]
puts f["+--++-=-+-+-"]
puts f["======"]

산출

390624=390624
390624=390624=390624
390623+1=390624
390624=390623+1
390625-1=390624
390624=390625-1
390624=390625-1=390624
390624=390623+1=390624
390624=390624=390624=390624
390623+1=390625-1
390625-1=390623+1
390623+1=390623+1
390625-1=390625-1
390626-1-1=390624
390622+1+1=390624
390624-1+1=390624
390624+1-1=390624
390624+1-1=390625-1=390624
390626-1-1=390626-1-1
390624=390624=390625-1=390624=390624
390624=390622+1+1=390624+1-1=390624-1+1=390626-1-1=390624
390624+1-1-1+1+1-1=390625-1+1-1+1-1
390624=390624=390624=390624=390624=390624=390624

2

PHP, 207 204 197 114 바이트

직접 접근 : 훨씬 짧고 빠름

foreach(explode("=",$argn)as$t)echo"="[!$c],strlen($argn)+($c=count_chars($t))[45]-$c[43],@chunk_split($t,!!$t,1);

온라인으로 실행 echo '<input>' | php -nR '<code>'하거나 테스트하십시오 .

고장

foreach(explode("=",$argn)as$t) // loop through terms
    echo                            // print ...
        "="[!$c],                       // 1. "=" if not first term
        strlen($argn)                   // 2. maximum number
            +($c=count_chars($t))[45]   //    + number of "-"
            -$c[43],                    //    - number of "+"
        @chunk_split($t,!!$t,1);        // 3. each operator followed by "1"
  • !$c1문자열 인덱싱 을 위해 캐스트 된 첫 번째 반복에서 true입니다 . "="[1]비었다.
    그 후, $c설정되고 !$c거짓, 캐스트로 0하고 "="[0]첫 번째 문자입니다.
  • 임의의 항에 대한 최대 값은 +1을 초과 할 필요는 없습니다.
    입력의 길이가 안전합니다. 모든 용어가이를 평가합니다.
  • chunk_split($s,$n,$i)-의 $i모든 $n문자 뒤에 $s그리고 끝에 삽입합니다 .
    빈 용어가로 바뀌지 않도록 1청크 길이를로 설정하면 오류가 발생합니다 0.

1

로다 , 112 (110) 109 바이트

f x{[(`:$x:`/"=")()|{|p|p~=":",""a=p;a~=`\+`,""b=p;b~="-","";["=",#x-#b+#a];{(p/"")|{|o|[o,"1"*#o]}_}}_][1:]}

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

이 프로그램에서 의도 한대로 스플릿 기능이 작동하지 않았습니다. 예를 들어, split("", sep="")아무것도 아닌 하나의 빈 문자열을 반환합니다. 그것은 어떻게 논리적입니까? 이로 인해 프로그램은 분할 의미론이 이상적 일 수있는 것보다 거의 20 바이트 더 큽니다.

이 답변의 아이디어는 입력 문자열의 길이가 방정식의 값보다 크거나 같아야한다는 것을 알고 있으므로 방정식의 값을 문자열의 길이로 정의합니다. 방정식의 모든 부분에 대해, 우리는 모든 연산자가 +1또는 -1빼고 있다고 생각 하여 방정식의 값에 더합니다.

언 골프 드 :

function f(x) {
    /* Adds ":"s around the string to prevent "=" being split wrong. */
    [split(`:$x:`, sep="=") | for p do
        p ~= ":", ""          /* Removes colons. */
        a := p; b := p        /* Initializes a and b to be p. */
        a ~= "\\+", ""        /* The lengths of a and are now equal to the */
        b ~= "-", ""          /* numbers of "-" and "+" characters in x. */
        push("=", #x-#b+#a)   /* Prints "=" and the value of the equation */
                              /* minus number of "+"s plus number of "-"s. */
        split(p, sep="") | for o do /* For each operator: */
            push(o)                 /* Prints the operator. */
            push(1) if [o != ""]    /* Prints 1 unless the operator is "". */
        done
    done][1:] /* Removes the first character of the output ("="). */
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.