제곱 차이를 최대화


19

의 정수 값의 순열 고려 1에를 N. 예를 들면 다음과 N = 4같습니다.

[1, 3, 4, 2]

우리는이 목록이 순환 그러한이라고 생각합니다 12인접으로 처리됩니다. 이러한 목록에 대해 계산할 수있는 수량은 인접 값의 총 제곱 차이입니다.

(1-3)² + (3-4)² + (4-2)² + (2-1)² = 10

당신의 임무는 양의 정수가 주어지면이 수량을 최대화하는 순열을 찾는 것 N입니다. N = 4위 예제 의 경우 최적이 아닙니다 (사실, 최소). 18다음 순열 (및 다른 순열)과의 총 제곱 차이를 얻을 수 있습니다 .

[1, 4, 2, 3]

알고리즘은 다항식 시간 ( N)으로 실행해야합니다 . 특히 모든 순열의 총 제곱 차를 간단히 계산할 수는 없습니다.

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

출력은 편리하고 모호하지 않은 플랫 목록 또는 문자열 형식 일 수 있습니다. 당신은에서 값 목록을 반환하도록 선택할 수 있습니다 0N-1대신 1N.

표준 규칙이 적용됩니다.

테스트 데이터

이 문제에 대한 훌륭한 분석 솔루션이 있습니다. 예를 들어 모든 유효한 솔루션 N = 10은 다음 목록과 같습니다 (순환 이동 및 반전).

[7, 5, 6, 4, 8, 2, 10, 1, 9, 3]

나는 그 이상으로 너무 많은 것을 밝히고 싶지 않기 때문에 (패턴을 알아내는 것으로 충분하더라도) 더 많은 예제를 제공하는 대신 결과에 주어진 결과에 대해 다음과 같은 제곱 차이가 있는지 확인할 수 있습니다 N.

N    Total squared difference

1                         0
2                         2
3                         6
4                        18
5                        36
6                        66
7                       106
8                       162
9                       232
10                      322
33                    11936
100                  333202
333                12308236
1000              333332002

이것은 OEIS 항목 A064842입니다 (이 문제에 대한 해결책이있는 용지에 대한 참조도 포함되어 있습니다).

답변:


7

젤리, 24 21 15 14 10 9 바이트

RUĖµ«/€ị"

총 제곱 차이를 계산하려면 µ_ṙ1$²S코드에 추가 하십시오. 온라인으로 사용해보십시오!

배경

최대 제곱 차이로 순열을 생성하는 한 가지 방법은 정수 1 에서 n 까지 오름차순으로 가져오고 왼쪽에서 두 번째를 오른쪽에서 두 번째로 바꾸고 왼쪽에서 네 번째를 오른쪽에서 네 번째로 바꾸는 것입니다. 우리가 중간에서 만날 때까지.

예를 들어, n = 8, 9의 경우

1 2 3 4 5 6 7 8        1 2 3 4 5 6 7 8 9
  ^   ^ ^   ^            ^   ^   ^   ^

(캐럿은 정수를 스왑으로 표시), 그 결과

1 7 3 5 4 6 2 8        1 8 3 6 5 4 7 2 9

교환 후.

n 의 패리티와 독립적으로 이러한 스왑을 달성하는 한 가지 방법 은 다음과 같습니다.

정수를 오름차순과 내림차순으로 하나씩 시작하십시오.

1 2 3 4 5 6 7 8        1 2 3 4 5 6 7 8 9
8 7 6 5 4 3 2 1        9 8 7 6 5 4 3 2 1

각 정수 쌍에 대해 최소 쌍을 계산하십시오. 이것은 가장 가까운 가장자리까지의 거리, 즉 왼쪽 또는 오른쪽의 색인 (둘 중 낮은 쪽)을 제공합니다.

1 2 3 4 5 6 7 8        1 2 3 4 5 6 7 8 9
8 7 6 5 4 3 2 1        9 8 7 6 5 4 3 2 1

1 2 3 4 4 3 2 1        1 2 3 4 5 4 3 2 1

최소값이 홀수이면 정수는 그 자리에 있어야하므로 첫 번째 행에서 정수를 선택합니다. 짝수이면 정수를 교체해야하므로 두 번째 행에서 정수를 선택하십시오.

1   3     6   8        1   3   5   7   9
  7   5 4   2            8   6   4   2

원하는 출력입니다.

작동 원리

RUĖµ«/€ị"    Main link. Input: n

R            Range. Yields [1, ..., n].
 U           Upend. Yields [n, ..., 1].
  Ė          Enumerate. Yields p := [[1, n], [2, n-1], ... [n-1, 2], [n, 1]].

   µ         Begin a new, monadic chain. Argument: p
     /       Reduce...
      €        each pair of p...
    «          by minimum.
        "    For each minimum and the corresponding pair of p:
       ị       Select the element at that index.
            Indices are modular and 1-based in Jelly, so this selects the first
            element if the minimum is odd, and the second one if it is even.

6

자바 스크립트 (ES6), 52 바이트

n=>[...Array(n)].map((_,i)=>(i<n/2|n%2)^i%2?i+1:n-i)

@Neil 덕분에 9 바이트가 절약되었습니다!

설명

이 방법 은 결과를 배열에 연결하지 않고 i길이가 인덱스 인 숫자를 결정합니다 n. 이는 다음 관찰을 기반으로합니다 ( n = 7예 : 사용 ).

  • 왼쪽에서 가장 낮은 숫자로 시작하고 오른쪽에서 가장 높은 숫자로 시작하십시오. [ 1, 7 ]
  • 가장 낮은 값이 오른쪽에 있고 가장 높은 값이 왼쪽 에 있도록 순서를 전환하고 가장 낮은 값을 늘리고 가장 높은 값을 줄인 다음 배열의 중간에 배치하십시오.[ 1, 6, 2, 7 ]
  • 최고 및 최저 수렴이 될 때까지 반복하십시오. [ 1, 6, 3, 4, 5, 2, 7 ]

상한 및 하한 번호 쉽게 같이 표현 될 수 n-ii+1각각.

var solution =

n=>
  [...Array(n)] // create an array of length n
  .map((_,i)=>  // set each value of the array at index i
    (i<n/2      // if we're on the left side,
    |n%2)       // or we're on the right and n is odd, even i => lower, odd i => higher
    ^i%2?       // else even i => higher, odd i => lower
    i+1:n-i
  )
N = <input type="number" id="input" oninput="result.textContent=solution(+this.value)" />
<pre id="result"></pre>


좋은 알고리즘; 나는 수식을 생성하려고 시도했지만 실패했습니다. 그래서 나는 더 추악한 푸시 및 언 쉬프트 방법을 사용해야했습니다. 그러나 나는 물론 당신의 논리를 단순화 할 수 있습니다 (i<n/2||n%2)^i%2?i+1:n-i.
Neil

@Neil Wow, 나는 방금 일어 났고, 이것을 골로 결심하고 당신의 정확한 논리를 생각해 내고 그것을 게시하자마자 입력하기 시작했습니다! 미친 ...
user81655

5

Python2, 105 98 바이트

@Dennis의 코멘트 덕분에 7 바이트 절약

n=input()
r=([],[n/2+1])[n%2]
for i in range(n/2,0,-1):k=[n+1-i];r=([i]+r+k,k+r+[i])[i%2]
print r

편집 된 버전 58 바이트

lambda n:[(n-i-1,i)[(i+(n,1)[i<n/2])%2]for i in range(n)]

나는 이미 하나의 라이너로 할 수 있어야한다고 생각했지만 논리는 나에게 너무 복잡했습니다. @ user81655의 JavaScript 답변과 @Dennis Python-answer의 람다 표기법을 보면서 새로운 시도를했습니다.

조건은

if i < n/2:
    i%2 != n%2
else:
    (i+1)%2

불행히도 모든 변환 노력은 JavaScript-logic 의 직접 변환과 비교하여 1 바이트 만 절약합니다 (i<n/2or n%2)!=i%2.


3
프로그래밍 퍼즐 및 코드 골프에 오신 것을 환영합니다! 이것은 Python 2 인 것처럼 보이므로 int()입력 주위를 필요로하지 않습니다 . 또한 for 루프의 본문을 같은 줄에 넣을 수 있습니다 for....
Dennis

4

파이썬, 51 49 바이트

lambda n:[(i^min(i,~i%n)%-2)%n for i in range(n)]

2 바이트를 골라 낸 @xnor에게 감사드립니다!

Ideone에서 사용해보십시오 .

작동 원리

경우 에 숫자 - [1 0, ..., N] , 다음 ~ I % N = - (I + 1) % N은 = - (I + 1) + N = (N - 1) - I , 이 매핑 즉 0 으로 1 - N , 1N - (2) 일반적으로, 및 상기 J 번째 상기 왼쪽에서 항목 j 개의 번째 오른쪽.

Jelly 답변 에서 설명한 것처럼 i~ i % n 중 더 낮은 값으로 엿보기로 출력을 구성하고 짝수이면 i를 선택 하고 홀수이면 ~ i % n을 선택할 수 있습니다. 우리는 이것을 다음과 같이 달성합니다.

  • 최소한도이면, min(i,~i%n)%-2수득한다 0 이렇게하여 배타적 논리합 결과, 수득한다 난을 , 그 잔사를 모듈로 연산 N 반환 I를 .

  • 최소값이 홀수 이면 -1min(i,~i%n)%-2 을 산출 하므로 i로 결과를 XOR하면 ~ i 가 산출 되므로 전체 표현식이 원하는대로 ~ i % n 로 평가됩니다 .


조건부로을 수행하여 몇 개의 문자를 저장할 수 있습니다 (i^min(i,n+~i)%-2)%n.
xnor

그것은 짧을뿐만 아니라 미치도록 영리합니다. 감사합니다!
Dennis

2

PHP, 77 76 51 50 49 바이트

ISO 8859-1 인코딩을 사용합니다.

배열의 전반부를 다음과 같이 조립하십시오.

  • 홀수는 색인 값 (1, 3, 5)을 갖습니다.
  • 짝수의 값은 N+1-index(9, 7, 5)입니다.
  • 결과 1, 9, 3, 7, 5

배열의 후반부에서 가장 바깥 쪽 값은에 합산됩니다. N+1N-[left value], 왼쪽 값이 이미 알려진 곳 에서 해당 오른쪽 값을 얻을 수 있습니다.

for(;$k=$argv[1]-$j++;)echo" ",min($j,$k)%2?$j:$k;

다음과 같이 실행하십시오 (이는 또한 총 제곱 차이를 나타냅니다) ( -d미학에만 추가됨).

php -d error_reporting=32757 -r 'for(;$k=$argv[1]-$j++;)echo~ß,$x[]=min($j,$k)%2?$j:$k;  for(;$c=$x[+$i++];)$b+=($c-($x[$i]?:$x[0]))**2;echo"\n$b\n";' 10
  • 왼쪽 / 오른쪽 조건을 무시하여 바이트를 저장하여 두 번째 삼항을 괄호없이 중첩 할 수 있습니다.
  • Dennis 알고리즘을 부끄럽게 구현하여 25 바이트 절약
  • 이후 필요한 공간을 제거하여 바이트를 절약했습니다. echo
  • 공간을 생성하는 데 사용하여 바이트를 저장했습니다 .

1

파이썬 2, 100

이미 파이썬 답변이 있음을 알고 있지만 다르게 수행했을 수도 있습니다.

n=input();a=n%2;b=n/2;x=[b+1,b+a][a:]
for i in range(b+a-1):f=1-i%2*2;x=[x[-1]-f]+x+[x[0]+f]
print x

그리고 총점을 테스트하기 위해 추가로 :

def t(x,n):return sum((x[i]-x[(i+1)%n])**2for i in range(n))

def t(x,n):return sum((x[i]-x[i-1])**2for i in range(n))음수 인덱스의 암시 적 랩 어라운드를 사용하고 4 바이트를 절약합니다. 나는 경쟁의 일부가 아니라는 것을 안다. ;)
btwlf

1

CJam, 17 15 14 바이트

{,W%ee_::e<.=}

스택에서 정수 n 을 팝하고 그 대가 로 [0… n-1] 의 순열을 푸시 하는 함수입니다 . 코드는 Jelly 답변 과 동일한 접근 방식을 사용합니다 .

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

작동 원리

,W%ee_::e<.=    Function body. Stack: N

,               Turn N into [0 ... N-1].
 W%             Reverse to push [N-1 ... 0].
   ee           Enumerate. This pushes [[0 N-1] [1 N-2] ... [N-2 1] [N-1 0]].
     _          Push a copy of the array of pairs.
      ::e<      Reduce each pair by minimum.
          .=    Vectorized selection.
                For the Ith minimum M, select the Mth element of the Ith pair.
                Indices are modular and 0-based in CJam, so this selects the first
                element if the minimum is even, and the second one if it is odd.

1

LISP, 86 바이트

(defun g(n m)(if(= n m)(list n)(if(< m n)(cons m(reverse(cons n(g(- n 1)(+ m 1))))))))

함수의 입력으로 시퀀스의 시작 (m) 및 종료 (n) 값을 선택할 수 있습니다.

제공된 샘플에 따라 기능을 테스트하기 위해 n은 N으로 고정되고 m은 1로 고정됩니다.

함수를 테스트하는 코드는 다음과 같습니다.

    (defun g(n m)(if(= n m)(list n)(if(< m n)(cons m(reverse(cons n(g(- n 1)(+ m 1))))))))

(defun sq (c)
    (apply #'+ (mapcar #'(lambda(x y) (* (- x y) (- x y))) c (append (cdr c) (list (car c))))))

(format t "N~20TSequence~50TSquared Difference~%")
(mapcar #'(lambda (x)(format t "~S~20T~S~50T~S~%" x (g x 1) (sq (g x 1)))) '(1 2 3 4 5 6 7 8 9 10 33 100 333 1000))

Ideone에서 사용해보십시오 !


1

줄리아, 39 바이트

n->map(i->min(i-1,n-i)%2>0?n-~-i:i,1:n)

이것은 1 : n 순열을 인쇄합니다 . 0 : n-1 의 순열은 비용이나 바이트를 절약하지 않습니다.

n->map(i->min(i,n+~i)%2>0?i:n+~i,0:n-1)

이 마지막 버전은 내 파이썬 답변 의 직접 포트입니다 .


0

ES6, 77 바이트

n=>[...Array(n)].map(_=>r[++i&2?"push":"unshift"](i&1?n--:++j),i=j=0,r=[])&&r

i&1샘플 중간에 너무 높거나 낮은 곳에 자리. 는 i&2쌍 결과의 시작 또는 끝 부분에 추가합니다.


0

R, 117 86 바이트

z=1:(n<-scan());a=pmin(z,n:1);for(i in seq(2,,2,n%/%2))z[b]=z[rev(b<-which(a==i,T))];z

편집 @Dennis '젤리 알고리즘의 구현과 버그 긴 버전을 대체

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