스칼라 , 764 바이트
object B{
def main(a: Array[String]):Unit={
val v=false
val (m,l,k,r,n)=(()=>print("\033[H\033[2J\n"),a(0)toInt,a(1)toInt,scala.util.Random,print _)
val e=Seq.fill(k, l)(v)
m()
(0 to (l*k)/2-(l*k+1)%2).foldLeft(e){(q,_)=>
val a=q.zipWithIndex.map(r => r._1.zipWithIndex.filter(c=>
if(((r._2 % 2) + c._2)%2==0)!c._1 else v)).zipWithIndex.filter(_._1.length > 0)
val f=r.nextInt(a.length)
val s=r.nextInt(a(f)._1.length)
val i=(a(f)._2,a(f)._1(s)._2)
Thread.sleep(1000)
m()
val b=q.updated(i._1, q(i._1).updated(i._2, !v))
b.zipWithIndex.map{r=>
r._1.zipWithIndex.map(c=>if(c._1)n("X")else if(((r._2 % 2)+c._2)%2==0)n("O")else n("_"))
n("\n")
}
b
}
}
}
작동 원리
알고리즘은 먼저 잘못된 값으로 2D 시퀀스를 채 웁니다. 명령 행 인수를 기반으로 반복 횟수 (열기 상자)가 몇 개인지를 결정합니다.이 값을 상한으로 접습니다. 접기의 정수 값은 알고리즘이 실행해야하는 반복 횟수를 계산하는 방법으로 암시 적으로 만 사용됩니다. 이전에 작성한 채워진 순서는 접기의 시작 순서입니다. 이는 해당 부정확 한 값으로 새로운 2D 잘못된 값 시퀀스를 생성하는 데 사용됩니다.
예를 들어
[[false, true],
[true, false],
[true, true]]
로 바뀔 것입니다
[[(false, 0)], [(false, 1)]]
완전히 참 (길이가 0) 인 모든리스트는 결과리스트에서 생략됩니다. 그런 다음 알고리즘은이 목록을 가져 와서 가장 바깥 쪽 목록에서 임의의 목록을 선택합니다. 무작위 목록은 우리가 선택한 임의의 행으로 선택됩니다. 그 임의의 행에서, 우리는 난수, 즉 열 인덱스를 다시 찾습니다. 이 두 개의 임의의 인덱스를 찾으면 1000 밀리 초 동안 스레드를 잠들게됩니다.
수면이 끝나면 화면을 지우고 true
우리가 만든 임의의 지수로 업데이트 된 값 으로 새 보드를 만듭니다 .
이것을 올바르게 출력하기 map
위해 맵의 인덱스와 함께 사용 하고 압축하여 문맥에 맞게 만듭니다. 우리는 우리가 인쇄해야하는지에 대한 일련의 진리 값을 사용 X
하거나 어느 쪽 O
또는 _
. 후자를 선택하기 위해 인덱스 값을 가이드로 사용합니다.
흥미로운 것들
그것이 인쇄해야하는 경우 알아 내기 위해 O
또는를 _
, 조건이 ((r._2 % 2) + c._2) % 2 == 0
사용된다. r._2
현재 행 인덱스를 c._2
참조하고 현재 열 을 나타냅니다. 하나가 홀수 행에 있으면 1이 r._2 % 2
되므로 c._2
조건부에서 1 씩 오프셋 됩니다. 이렇게하면 홀수 행에서 열이 의도 한대로 1 씩 이동합니다.
"\033[H\033[2J\n"
내가 읽는 일부 Stackoverflow 답변에 따라 문자열을 인쇄 하면 화면이 지워집니다. 터미널에 바이트를 쓰고 실제로 이해하지 못하는 펑키 한 일을하고 있습니다. 그러나 나는 그것이 가장 쉬운 방법이라는 것을 알았습니다. 그러나 Intellij IDEA의 콘솔 에뮬레이터에서는 작동하지 않습니다. 일반 터미널을 사용하여 실행해야합니다.
이 코드를 처음 볼 때 이상한 점을 발견 할 수도 있습니다 (l * k) / 2 - (l * k + 1) % 2
. 먼저 변수 이름을 이해해 봅시다. l
프로그램에 전달 된 첫 번째 인수를 참조하고 두 번째 인수를 k
나타냅니다. 번역하려면 (first * second) / 2 - (first * second + 1) % 2
. 이 방정식의 목표는 모든 X의 시퀀스를 얻는 데 필요한 정확한 반복 횟수를 도출하는 것입니다. 내가 이것을 처음 할 때, 나는 (first * second) / 2
그 의미가 이해가되었습니다. n
각 하위 목록의 모든 요소에 대해 n / 2
버블을 터뜨릴 수 있습니다. 그러나 다음과 같은 입력을 처리 할 때 중단됩니다.(11 13)
. 두 숫자의 곱을 계산하고 짝수이면 홀수이고 홀수이면 모수를 2로 수정해야합니다. 홀수 인 행과 열에 반복이 한 번 덜 필요하기 때문에 작동합니다. 최종 결과를 얻을 수 있습니다.
map
forEach
문자 수가 적기 때문에 대신에 사용됩니다 .
아마 개선 될 수있는 것들
이 솔루션에 대해 정말로 나를 괴롭히는 것은 자주 사용하는 것입니다 zipWithIndex
. 너무 많은 캐릭터를 차지하고 있습니다. zipWithIndex
전달 된 값으로 수행 할 수 있는 하나의 문자 함수를 정의 할 수 있도록 만들려고했지만 Scala는 익명 함수에 유형 매개 변수를 허용하지 않는 것으로 나타났습니다. 사용하지 않고 내가하고있는 일을하는 또 다른 방법이있을 수 zipWithIndex
있지만 그렇게 하는 영리한 방법에 대해서는별로 생각하지 않았습니다.
현재 코드는 두 단계로 실행됩니다. 첫 번째 보드는 새 보드를 생성하고 두 번째 패스는 보드를 인쇄합니다. 이 두 패스를 하나의 패스로 결합하면 몇 바이트를 절약 할 수 있다고 생각합니다.
이것은 내가 한 첫 번째 코드 골프이므로 개선의 여지가 많이 있다고 확신합니다. 가능한 한 바이트를 최적화하기 전에 코드를 보려면 여기에 있습니다.
1
및0
대신O
하고X
?