정수 쌍을 같게하기


51

이것은 내가 인터넷 어딘가에 보았다 수학 문제에서 영감을했지만 위치를 기억하지 않습니다 (UPDATE : 원래 문제가 발견 된 하위 Reddit 수학 수수께끼 가 가능하다는 것을 제공 증거로도 볼 이 수학 SE 게시물을 ) 요구를 임의의 정수 쌍에 대해 다음 프로세스가 가능한지 증명합니다 (내가 기억하는 것에서 주어진 쌍에 대해 가능했습니다).

한 쌍의 정수 j와 k가 주어지면, 그것들 중 하나를 두 배로 늘리고 다른 하나를 더하여 (j, k)-> (j + 1, k * 2) 또는 (j * 2, k + 1). 그런 다음 정수 쌍을 동일하게 유지하려는 목적으로 해당 정수로이 프로세스를 반복하십시오.

이 예제는 반드시 최적은 아니지만 양수, 음수 또는 0의 정수에서이 프로세스를 수행하는 방법을 보여줍니다.

(2, 5) -> (3, 10) -> (6, 11) -> (12, 12)

(5, 6) -> (6, 12) -> (7, 24) -> (14, 25) -> (28, 26) -> (56, 27) -> (112, 28) -> (113, 56) -> (226, 57) -> (227, 114) -> (228, 228)

(0, 2) -> (1, 4) -> (2, 5) -> (3, 10) -> (6, 11) -> (12, 12)

(-4, 0) -> (-3, 0) -> (-2, 0) -> (-1, 0) -> (0, 0)

(3, -1) -> (6, 0) -> (12, 1) -> (13, 2) -> (14, 4) -> (15, 8) -> (16, 16)

(-4, -3) -> (-8, -2) -> (-16, -1) -> (-32, 0) -> (-31, 0) -> ... -> (0, 0)

도전

두 개의 정수를 제공하는 프로그램을 작성하고 하나를 반복적으로 증가시키고 다른 하나를 두 배로 증가시켜 정수를 동일하게 만드는 데 필요한 단계 목록을 출력합니다.

사양

  • 솔루션은 최적 일 필요는 없지만 임의의 쌍에 대해 유한 한 단계로 해결해야합니다.
  • 입력은 2 개의 정수 여야합니다

  • 출력은 각 단계의 결과 정수를 명확하게 나타내는 합리적인 출력 일 수 있습니다. 예를 들면 다음과 같습니다.

    • 쌍으로 구분 된 두 개의 구분 기호 (기호, 공백 등)가있는 문자열
      • 예 : 입력 j, k : 2, 5-> 출력 : 3,10; 6,11; 12,12
    • 정수 목록
      • 예 : 입력 j, k : 2, 5-> 출력 : [[3, 10], [6, 11], [12, 12]]
  • 입력이 같은 숫자의 쌍이면 다른 사소한 답변과 일치하는 한 아무것도 출력 할 수 있습니다

    • 예를 들어
      • 입력 [2, 5]에 입력 쌍이 포함되지 않은 [[3, 10], [6, 11], [12, 12]] 출력이있는 경우 입력 [4, 4]는 아무것도 출력하지 않습니다.
      • 입력 [2, 5]에 입력 쌍이 포함 된 [[2, 5], [3, 10], [6, 11], [12, 12]] 출력이있는 경우 입력 [4, 4] 출력 [[4, 4]].
  • 표준 IO 방법 적용 및 표준 허점 금지

  • 이것은 코드 골프이므로 바이트 단위의 최단 답변


13
이것은 좋은 첫 번째 도전입니다, BTW. PPCG에 오신 것을 환영합니다!
Arnauld

@Arnauld 감사합니다! 또한 감사는 오류를 지적, 나는 모든 예제 손으로 정말 먼저 솔루션 자신을 구현해야 않았다
JMigst

출력을 반대로 할 수 있습니까? 예 [(12,12),(6,11),(3,10),(2,5)]를 들어 입력 (2,5)?
Laikoni

1
@Laikoni 여전히 출력하는 데 필요한 모든 단계를 고려, 나는 그것이 좋은 생각
JMigst

1
나는 이것을 OEIS에 A304027추가했다 . 쌍 (34,23)은 특히 어려운 것으로 보입니다.
피터 카게이

답변:


10

자바 스크립트 (ES6), 111 90 83 바이트

f=(a,b,p=q=[],u=[...p,[a,b]])=>a-b?f(...(q=[[a*2,b+1,u],[a+1,b*2,u],...q]).pop()):u

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

댓글

f = (                       // f = recursive function taking:
  a, b,                     //   (a, b) = input integers
  p =                       //   p[] = current path
  q = [],                   //   q[] = queue
  u = [...p, [a, b]]        //   u[] = updated path with [a, b] appended to it
) =>                        //
  a - b ?                   // if a is not yet equal to b:
    f(...                   //   recursive call, using spread syntax:
      (q = [                //     prepend the next 2 possible moves in the queue:
        [a * 2, b + 1, u],  //       a * 2, b + 1
        [a + 1, b * 2, u],  //       a + 1, b * 2
        ...q                //
      ]).pop()              //     use the move on the top of the queue
    )                       //   end of recursive call
  :                         // else:
    u                       //   success: return the (updated) path

9

하스켈, 70 69 바이트

f(w@((i,j):_):r)|i==j=w|1<2=f$r++[(i+1,j*2):w,(i*2,j+1):w]
g x=f[[x]]

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

간단한 BFS. 쌍 목록에서 단계를 추적합니다.

g x=f[[x]]                -- start with a single list where the only
                          -- step is the starting pair
f (w@((i,j):_):r) =       -- let w be the first list of steps
                          --     (i,j) the last pair of the first list of steps
                                       ('last' as in last operated on. As we store
                                        the steps in reverse order it's the
                                        first element in the list)
                          --     r all other lists of steps
   i==j=w                 -- if i==j stop and return the first list
   1<2= f                 -- else make a recursive call
          r++             -- where the new input list is r followed by
                          -- the first list extended one time by
          [(i+1,j*2):w,         (i+1,j*2) and one time by
             (i*2,j+1):w]       (i*2,j+1)

7

파이썬 3 , 90 74 72 바이트

Dennis 덕분에 -2 바이트 .

def f(a,*x):j,k=a[0];return(j==k)*a or f(*x,[(2*j,k+1)]+a,[(j+1,2*k)]+a)

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

입력을 싱글 톤리스트로 받습니다.


언 골프

def f(a,*x):              # function taking at least one argument
                          # a is the first argument, all other are stored in x
  j, k = a[0]             # get the newest values of the current path
  return (j==k)*a         # if j is equal to k return the current path
                  or      # else ...
   f(                     # continue ...
     *x,                  # with the remaining paths ...
     [(2*j,k+1)]+a        # and split the current path ...
     [(j+1,2*k)]+a        # in two new ones
    ) 

4

Pyth, 41 바이트

J]]QL,hhb*2ebWt{KehJ=J+tJm+hJ]d,yK_y_K)hJ

여기 사용해보십시오

설명

이것은 매우 간단한 너비 우선 검색입니다. 가능한 순서의 대기열을 유지하고 ( J) 일치하는 쌍을 얻을 때까지 다음 순서를 취하고 가능한 각 동작을 고수 한 다음 대기열의 끝에 놓습니다.
간결성을 위해 y람다 식 L을 사용하여 이동 중 하나를 수행 하는 함수를 정의하고 앞뒤로 적용합니다.



4

05AB1E , 25 22 20 바이트

이중 중첩 목록을 입력으로 취하고 각 단계마다 하나의 중첩 깊이에서 들쭉날쭉 한 목록을 출력합니다.

[ć¤Ë#¤xs>R‚ø`R‚s¸sâ«

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

설명

[                      # start a loop
 ć                     # extract the first element of the current list (current path)
  ¤Ë#                  # break if all elements in the head are equal
     ¤xs>              # duplicate one copy of the head and increment another
         R             # reverse the incremented copy
          ‚ø           # zip them together
            `R‚        # reverse the tail of the zipped list
               s¸sâ    # cartesian product with the rest of the current path
                   «   # append to the list of all current paths

4

레티 나 , 72 바이트

\d+
*
/\b(_+),\1\b/^+%`(_+),(_+)$
$&;_$&$2¶$=;$1$&_
G`\b(_+),\1\b
_+
$.&

온라인으로 사용해보십시오! 단항 산술의 한계로 인한 두 가지 테스트 사례. 설명:

\d+
*

단항으로 변환합니다.

/\b(_+),\1\b/^+

입력에 동일한 숫자 쌍이 포함되어 있지 않지만 ...

%`(_+),(_+)%

... 각 줄의 마지막 쌍과 일치합니다 ...

$&;_$&$2¶$=;$1$&_

... 라인을 두 줄로 바꾸십시오. 하나는 첫 번째 숫자가 증가하고 두 번째가 두 배가되고 다른 하나는 첫 번째 숫자가 두 배가되고 두 ​​번째가 증가합니다.

G`\b(_+),\1\b

일치하는 쌍으로 라인을 유지하십시오.

_+
$.&

십진수로 다시 변환합니다. 88 88 바이트 부호없는 10 진수 산술 버전 (0에서도 작동) :

/\b(\d+),\1\b/^+%`(\d+),(\d+)$
$&;$.(_$1*),$.(2*$2*)¶$=;$.(2*$1*),$.(_$2*
G`\b(\d+),\1\b

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


4

MATL , 24 바이트

`vxG1r/q:"tt1rEk(+]td0=~

실행 시간은 임의적이지만 확률 1로 유한합니다.

코드는 매우 비효율적입니다. 4 개 또는 5 개 이상의 단계가 필요한 입력은 온라인 인터프리터에서 시간 초과 될 가능성이 높습니다.

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

설명

`         % Do...while
  vx      %   Concatenate stack and delete. This clears the stack from contents
          %   of previous iterations   
  G       %   Push input
  1       %   Push 1
  r       %   Push random number uniformly distributed on (0,1)
  /       %   Divide
  q       %   Subtract 1. The result is a random number, t, that has nonzero
          %   probability of being arbitrarily large. Specifically, t is in
          %   the interval (0,1) with probability 1/2; in (1,2) with probability
          %   1/6; ... in (k,k+1) with probability 1/((k+1)*(k+2).
  :       %   Range [1 2 ... floor(t)]
  "       %   For each (that is: do thw following floor(t) times)
    tt    %     Duplicate twice
    1     %     Push 1
    rEk   %     Random number in (0,1), times 2, round down. This produces a 
          %     number i that equals 0 or 1 with probability 1/2
    (     %     Write 1 at entry i. So if the top of the stack is [a b], this
          %     transforms it into either [1 b] or [a 1]
    +     %     Add, element-wise. This gives either [a+1 2*b] or [2*a b+1] 
  ]       %   End for each
  td      %   Duplicate, consecutive difference between the two entries
  0=~     %   Is it not zero? If so, the do...while loop continues with a new
          %   iteration. Normally the code 0=~ could be omitted, because a
          %   nonzero consecutive difference is truthy. But for large t the
          %   numbers a, b may have gone to infinity, and then the consecutive
          %   difference gives NaN
          % End do...while (implicit). Display (implicit)

3

Stax , 29 26 바이트

ä⌠|Tô&cm♂NV↓↔╗╣¢♠╜╒█¡Φ≈ñY@

실행 및 디버깅

광범위한 첫 검색입니다. 합리적으로 빠른 것 같습니다.

이중 배열로 감싼 정수 쌍이 필요합니다. 출력은 공백으로 구분 된 값 목록입니다. 두 값은 모두 솔루션 경로의 한 쌍을 나타냅니다.



2

빨강 , 142 바이트

입력을 Red 형식으로 정수 쌍의 이중 중첩 블록으로 가져옵니다 (2, 5).->2x5

예를 들어, 빨간색 페어 목록으로 결과를 반환합니다 2x5 3x10 6x11 12x12. 초기 쌍을 포함합니다.

func[c][a: copy[]foreach d c[l: last d if l/1 = l/2[return d]do replace/all{%+ 1x0 * 1x2
%* 2x1 + 0x1}"%""append/only a append copy d l "]f a]

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

엄격한 입력 :

입력은 두 개의 숫자입니다 (예 : 2 5

빨강 , 214 바이트

func[a b][g: func[c][a: copy[]foreach d c[l: last d if l/1 = l/2[return d]append/only a append copy d l + 1x0 * 1x2
append/only a append copy d l * 2x1 + 0x1]g a]c: copy[]insert/only c reduce[do rejoin[a 'x b]]g c]

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

설명:

f: func[a b][                 
g: func[c][                                   ; recursive helper function
  a: copy[]                                   ; an empty block
  foreach d c[                                ; for each block of the input 
    l: last d                                 ; take the last pair
    if l/1 = l/2[return d]                    ; if the numbers are equal, return the block 
    append/only a append copy d l + 1x0 * 1x2 ; in place of each block append two blocks
    append/only a append copy d l * 2x1 + 0x1 ; (j+1, k*2) and (j*2, k+1)
  ]                                           ; using Red's arithmetic on pairs
  g a                                         ; calls the function anew
]
c: copy[]insert/only c reduce[do rejoin[a 'x b]]; prepares a nested block from the input
g c                                           ; calls the recursive function 
]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.