전문가처럼 님 보드를 시각화


10

배경

에서 님의 게임 각 턴에 플레이어가에서 한 모든 돌 사이에 제거해야합니다, 플레이어는 "더미"에서 "돌"을 제거 교대로 하나의 더미. Nim의 목표는 마지막 돌을 사용하거나 잘못 변형 된 경우 상대방이 그렇게하도록 강요하는 것이지만 전략은 거의 동일합니다.

님은 재미있는 바 게임을 만듭니다. "돌"에 성냥개비 나 동전을 사용할 수 있으며 "파일"은 일반적으로 한 줄로 배열됩니다. 아래는 1, 3, 5 및 7의 더미가있는 클래식 설정입니다.

성냥개비

이전에 Nim을 사용한 적이 없다면이 도전을 시도하기 전에 손을 사용해보십시오. 다음 은 "Pearls Before Swine"이라는 버전 입니다.

전략

Nim의 최적 전략은 대부분의 평신도들이 일관되게 전문가에게 잃을 정도로 이진 산술로 간단하게 설명하기에 까다 롭습니다 .

그러나 이진 XOR 연산을 수행하는 것은 어렵 기 때문에 운 좋게도 술에 취했을 때도 실시간으로 구현하기 쉬운 올바른 전략을 시각화하는 동등한 방법이 있습니다.

세 단계 만 있습니다.

  1. 각 라인의 "돌"을 크기가 2의 거듭 제곱 인 하위 그룹으로 정신적으로 그룹화합니다. 가능한 가장 큰 크기부터 시작합니다. 대부분의 게임에는 8, 4, 2 및 1이면 충분합니다.
  2. 모든 그룹이 한 쌍을 갖도록 각 그룹을 다른 라인의 쌍둥이와 일치 시키십시오.
  3. 이것이 가능하지 않은 경우, 한 줄에서 짝을 이루지 않은 "돌"을 제거하십시오 (이것은 항상 가능합니다-이유는 Wikipedia 링크 참조).

또는 다른 방법으로 말했다 : "단일 파일에서 석재를 제거하여 파일을 2의 거듭 제곱으로 묶으면 모든 그룹이 다른 파일의 그룹과 쌍을 이룰 수 있습니다." 2의 큰 거듭 제곱을 더 작은 거듭 제곱으로 나눌 수 없다는 경고가 있습니다.

예를 들어 다음은 위의 보드를 시각화하는 방법입니다.

균형 잡힌 성냥개비

이 보드는 완벽하게 균형을 이루므로 상대방이 먼저 움직이기를 원할 것입니다.

도전

Nim "piles"의 크기를 나타내는 양의 정수 목록이 제공되면 전문가가 보는 것처럼 Nim 보드의 일반 텍스트 시각화를 반환합니다.

유효한 시각화를 구성하는 것은 예제를 통해 가장 잘 설명 할 수 있지만 다음을 수행해야합니다.

  1. 각 "2의 거듭 제곱 하위 그룹"과 해당 쌍에 개별 문자를 할당하고 (쌍으로 묶지 않은 하위 그룹은 자격이 없음) 해당 문자를 사용하여 하위 그룹과 쌍에서 "돌"을 나타냅니다.
  2. 하이픈을 사용하여 짝을 이루지 않은 "돌"(즉, 전문가가 Nim을 잘못 연주하지 않을 때 제거 할 돌)을 나타냅니다 -.

유효한 시각화를 달성하는 방법에는 여러 가지가 있으며 모두 유효합니다. 몇 가지 테스트 사례를 살펴 보겠습니다.

테스트 사례

입력 : 1, 3, 5, 7

가능한 출력 1 :

A
BBA
CCCCD
CCCCBBD

선택적으로 문자 사이에 공백과 행 사이에 빈 줄을 포함시킬 수 있습니다.

가능한 출력 2 :

A

B B A

C C C C D

C C C C B B D

입력 : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

캐릭터의 순서와 선택은 원하는대로 될 수 있습니다.

가능한 출력 1 :

G
E E
E E G
C C C C
C C C C F
B B B B D D
B B B B D D F
H H I - - - - -
A A A A A A A A I
A A A A A A A A H H

유니 코드 기호도 괜찮습니다.

가능한 출력 2 :

◎
◈  ◈
◈  ◈  ◎
△  △  △  △
△  △  △  △  ◉
◐  ◐  ◐  ◐  ◀  ◀
◐  ◐  ◐  ◐  ◀  ◀  ◉
▽  ▽  ◒  -  -  -  -  -
▥  ▥  ▥  ▥  ▥  ▥  ▥  ▥  ◒ 
▥  ▥  ▥  ▥  ▥  ▥  ▥  ▥  ▽  ▽  

입력 : 7

규칙에 따라 모든 "단일 파일"을 완전히 제거해야합니다.

가능한 출력 1 :

-------

가능한 출력 2 :

- - - - - - -

입력 : 5, 5

가능한 출력 :

A A A A B
A A A A B

추가 규칙

  • 이것은 표준 규칙을 가진 코드 골프입니다. 가장 짧은 코드가 승리합니다.
  • 입력은 융통성이 있으며 편리한 목록 형식으로 가져올 수 있습니다.
  • 위의 예와 같이 출력도 유연합니다. 가장 합리적인 변형이 허용됩니다. 확실치 않은 것이 있는지 물어보십시오.

1
각 파일에 포함 할 수있는 석재 수 또는 시각화에 필요한 고유 문자 수에 제한이 있습니까? (예를 들어, 인쇄 가능한 ASCII 문자 수보다 많거나 255 개 이상의 고유 문자가 필요한 경우 어떻게해야합니까?)
Doorknob

@Doorknob 당신은 그런 일이 일어나지 않을 것이라고 생각할 수 있습니다. 알파벳 문자가 모든 입력에 충분하다고 가정 할 수도 있습니다.
요나

@Jonah 이것은 두 번째 테스트 사례에 유효한 출력입니까? ["H","EE","EEH","CCCC","CCCCI","DDDDFF","DDDDFFI","AAAAAAAA","AAAAAAAA-","----------"]
ngn

1
@ Οurous 나는 간단한 대답이 예라고 생각합니다. 기술적 AAAABBBB으로 실제로는 유효하지 ABB않지만 그렇지 않습니다. 그러나 출력을 읽기 어렵게 만들므로 한 줄 내에서 명시 적 규칙을 줄이는 것이 가장 좋습니다.
Jonah

1
@JonathanAllan 네, 3 단계가 모두 동시에 이루어져야한다는 논리에 의존하고 있습니다. 따라서 1 단계와 2 단계를 수행하지만 3 단계를 수행 할 수없는 경우 솔루션을 1 단계와 2 단계로 조정해야합니다. 혼동 될 수 있습니다. 아래에 설명을 추가했습니다.
요나

답변:


2

루비, 169 (164) 148 바이트

->a{s=eval a*?^
c=?@
m={}
a.map{|x|z=x-(x^s);[$><<?-*z,x-=z,s=0]if z>0
n=1
eval'x&1>0?[$><<(m[n]||c.next!)*n,m[n]=!m[n]&&c*1]:0;n*=2;x/=2;'*x
puts}}

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

먼저 초기화

  • NIM과 합 s=eval a*?^(보다 작은 a.reduce:^)
  • c사용하지 않는 첫 번째 고유 문자를 저장 하는 변수
  • m2의 거듭 제곱을 길이를 나타내는 데 사용되는 문자 로 매핑 하는지도

그런 다음 각 파일을 반복하여 다음을 실행합니다.

z=x-(x^s);[$><<?-*z,x-=z,s=0]if z>0

위키 백과의 전략 경우, NIM-합계 XOR의 더미 미만이다 더미 , 우리는 그 길이가되도록 그 더미에서 돌을 제거해야 NIM-합계 XOR 더미 . 변수에 차이를 저장 z하여이 차이가 양수인지 여부를 테스트 할 수 있으며, 그렇다면 1.) 많은 대시를 인쇄하고, 2) 파일에서 빼고, 3. nim-sum 변수를 추가 석재 제거를 방지하기 위해 0.

n=1
eval'[...];n*=2;x/=2;'*x

이제 우리는 각 비트에 대해 "루프" 하고 누산기 를 반복적으로 나누고 곱 x함으로써 그 값을 추적 합니다 . 루프는 실제로 평가 된 시간으로, 필요한 시간 보다 훨씬 길지만 비효율을 제외하고는 아무런 해가 없습니다. 비트가 1 ( ) 이면 각 비트에 대해 다음을 실행합니다 .2n2xlog2(x)x&1>0

$><<(m[n]||c.next!)*n

문자 n시간을 인쇄하십시오 . 이 많은 석재의 짝을 이루지 않은 그룹을 이미 인쇄 한 경우 해당 문자를 사용하십시오. 그렇지 않으면 다음으로 사용되지 않는 문자를 사용하십시오 ( c로 인해 전진 !).

m[n]=!m[n]&&c*1

m[n]존재하는 경우 (즉, 방금 쌍을 완료 한 경우) m[n]재설정됩니다. 그렇지 않으면, 우리는 방금 새 쌍을 시작 했으므로 m[n]우리가 사용한 문자로 설정 합니다 ( *1의 복사본을 만드는 짧은 방법입니다 c).


4

파이썬 2 , 150 196206 바이트

def f(p):
 c=48;s=[l*'.'for l in p];m=2**len(bin(l))
 while m:
  if sum(m*'.'in l for l in s)>1:
   for i,l in enumerate(s):s[i]=l.replace('.'*m,chr(c)*m,`s`.count(chr(c)*m)<2)
   c+=1
  else:m/=2
 return s

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


나는 이것이 효과가 없다고 생각한다 4, 9, 10.
Neil

@Neil Nice 캐치가 수정되었습니다.
TFeld

1
죄송합니다 14, 21, 35. 이번에는으로 다시 속 였습니다.
Neil

[1, 3, 4, 5]에서도 실패하여 전체 두 번째 파일을 제거해야합니다.
Doorknob

@Doorknob, 이것이 필요합니까? 규칙은 말한다There will be multiple ways to achieve a valid visualization, and all are valid
TFeld

1

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

f=
(a,c=0,x=eval(a.join`^`),i=a.findIndex(e=>(e^x)<e),b=a.map(_=>``),g=e=>(d=e&-e)&&a.map((e,i)=>e&d&&(a[i]-=d,b[i]=(c++>>1).toString(36).repeat(d)+b[i]))&&g(e-d))=>g(eval(a.join`|`),b[i]='-'.repeat(a[i]-(a[i]^=x)))||b
<textarea oninput=o.textContent=/\d/.test(this.value)?f(this.value.match(/\d+/g)).join`\n`:``></textarea><pre id=o>

최대 36 개의 다른 캐릭터 만 시각화합니다. 나는 이것이 효과가 있다고 안심했다 1, 3, 4, 5.


정말 좋아요 실시간으로 재미있게 놀아요.
요나

1

클린 , 454 바이트

여전히 골프

import StdEnv,Text,Data.List
$p=join"\n"[{#toChar c+'-'\\c<-e}\\e<-[take i(e++[0,0..])\\e<-r[[~c\\c<-reverse e,_<-[1..c]]\\e<-hd[q\\q<-foldr(\h t=[[a:b]\\a<-h,b<-t])[[]][[c\\c<-subsequences(takeWhile((>=)k)(iterate((*)2)1))|sum c<=k]\\k<-p]|sum[1\\a<-q&b<-p|sum a<>b]<2&&foldr(bitxor)0(flatten q)==0]]1&i<-p]]
r[]_=[]
r[h:t]n|all((<)0)h=[h:r t n]
#[m:_]=removeDup[e\\e<-h|e<0]
#(a,[x:b])=span(all((<>)m))t
=r([[if(e==m)n e\\e<-k]\\k<-[h:a]++[x]]++b)(n+1)

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

$ :: [Int] -> String파일 크기를 가져와 -제거 할 스톤을 나타내는 문자열을 반환 하고 그룹은에서 오름차순으로 ASCII 문자로 표시되는 함수를 정의합니다 -. 충분한 그룹이 필요한 경우 문자가 결국 줄 바꿈 foldr되므로 두 번째 테스트 사례를 실행하려면 기가 바이트 이상의 메모리가 필요합니다.

거대 이해력의 들여 쓰기 버전 :

$p=join"\n"[
    {#
        toChar c+'-'
        \\c<-j
    }
    \\j<-[
        take i(e++[0,0..])
        \\e<-r[
            [
                ~c
                \\c<-reverse e
                ,_<-[1..c]
            ]
            \\e<-hd[
                q
                \\q<-foldr(\h t=[
                    [a:b]
                    \\a<-h
                    ,b<-t
                ])[[]][
                    [
                        c
                        \\c<-subsequences(takeWhile((>=)k)(iterate((*)2)1))
                        |sum c<=k
                    ]
                    \\k<-p
                ]
                |sum[
                    1
                    \\a<-q
                    &b<-p
                    |sum a<>b
                ]<2&&foldr(bitxor)0(flatten q)==0
            ]
        ]1
        &i<-p
    ]
]

그냥 궁금해서, Clean은 haskell과 비슷해 보입니다 ... Haskell에 비해 그 장점은 무엇입니까?
Jonah

1
@Jonah 그렇습니다. 내 머리 꼭대기에는 하위 수준 유형 조작, 인라인 IL / 어셈블리 및 C와의 상호 운용성이 Haskell보다 쉽습니다. 그러나 실제 사용을 위해 Clean의 모호함과 실험 / 학문적 특성으로 인해 Haskell (도서관 및 참조 정보 측면에서 더 많은 지원을 제공함)을 권장합니다. 난 그냥 청소가 모두 좋아 좋아.
OUurous
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.