Karel J. AlphaBot 시퀀스 생성기


14

점수

이 섹션은 제출이 입력되면 채워집니다.

표준

1. bopjesvla    Perl                54
2. edc65        Javascript (ES6)    91
3. name         language            score
4. name         language            score
5. name         language            score

보너스 라운드

1. name   language   score
2. name   language   score
3. name   language   score
4. name   language   score
5. name   language   score

카렐 제이 알파 봇

배경

Java에 대한 인기있는 입문 과정은 Karel J. Robot입니다 (직접 사용하고 있습니다). 로봇은 거리 그리드 (양의 정수 y 좌표) 및 도로 (양의 정수 x 좌표)와 그리드에 배치하고 저장할 수있는 신호음과 상호 작용합니다 (Karel 및 모든 신호음은 격자에만 존재할 수 있음에 유의하십시오) 포인트들). Karel (로봇)은 5 가지 동작 만 수행합니다. 앞으로 1만큼 이동하고, 왼쪽으로 돌리고, 신호음을 내고, 신호음을 내고, 끄십시오.

내 컴퓨터 과학 수업에서 우리의 첫 번째 임무 중 하나는 Karel이 우회전, 돌고, 1 씩 앞으로 나아가고 신호음을 내리는 결합 된 행동을 수행하는 방법을 배우도록 프로그램하는 것이 었습니다. 며칠 후 과제는 이러한 방법을 사용하고 알파벳 문자를 생성하는 새로운 방법을 작성하는 것이 었습니다.

당연히이 과제를 마치면 알파벳의 모든 문자와 10 자리 숫자를 만드는 더 많은 방법을 작성했으며 로봇에서 일종의 워드 프로세서를 만드는 방법을 알아낼 계획입니다. STDIN에 입력되고 로봇은 문자와 유사한 방식으로 신호음을 그리드에 놓습니다.

private void draw#각 문자에 대해 쓸 때마다 #필요한 명령 순서의 약어를 알려주는 주석을 추가했습니다.

나는 다음과 같은 명령 (의사 코드로 작성 됨)을 가지고 있습니다 (설명-유일 하게 유용한 명령입니다).

Turn Left
    Rotate the robot 90˚ counterclockwise
    Abbreviated as "l"

Turn Right
    Rotate the robot 90˚ clockwise
    Abbreviated as "r"

Move
    Move one space forwards
    Abbreviated as "m"

Put Beeper
    Put a beeper on the spot that Karel is on
    Abbreviated as "p"

Drop Beeper
    Move, then Put Beeper
    Abbreviated as "d"

Turn Around
    Turn Left, then Turn Left
    Abbreviated as "a"

정황

로봇은 다음 순서로 진행해야합니다.

  • 로봇은 글자가 그려지는 최소 영역의 5xN 직사각형 왼쪽 하단에서 시작합니다.
  • 로봇이 편지를 그립니다.
  • 로봇이 직사각형의 오른쪽 하단으로 이동합니다.
  • 로봇은 오른쪽으로 2 칸 이동 하며 북쪽 / 위를 향해야합니다

예를 들어 봅시다. 우리가 그리기를 원한다고 가정하자 A. 로봇의 위치는 방향 (북쪽, 남쪽, 동쪽, 서쪽)을 나타내는 문자입니다. 로봇이 신호음이없는 지점에 있으면 문자가 대문자로 표시되고 로봇이 신호음이없는 위치에 있으면 소문자로 표시됩니다. o신호음이있는 반점과 신호음 .이없는 반점을 나타냅니다.

나중에 볼 수 있듯이 A이것입니다.

.ooo.
o...o
ooooo
o...o
o...o

가능한 해결책은 다음과 같습니다.

Grids   .....   .....   .....   .....   .....   .....   .....   .....   .....
        .....   .....   .....   .....   .....   .....   .....   .....   .....
        .....   .....   .....   N....   E....   oE...   ooE..   oooE.   oooW.
        .....   .....   N....   o....   o....   o....   o....   o....   o....
        n....   N....   o....   o....   o....   o....   o....   o....   o....

Letters           p       d       d       r       d       d       d       a

        .....   .....   .....   .....   .....   n....   e....   .E...   .oE..
        .....   .....   .....   .....   N....   o....   o....   o....   o....
        ooWo.   oWoo.   Wooo.   Nooo.   oooo.   oooo.   oooo.   oooo.   oooo.
        o....   o....   o....   o....   o....   o....   o....   o....   o....
        o....   o....   o....   o....   o....   o....   o....   o....   o....

          m       m       m       r       d       m       r       d       d

        .ooE.   .oooe   .ooos   .ooo.   .ooo.   .ooo.   .ooo.   .ooo.
        o....   o....   o....   o...S   o...o   o...o   o...o   o...o
        oooo.   oooo.   oooo.   oooo.   ooooS   ooooo   ooooo   ooooo
        o....   o....   o....   o....   o....   o...S   o...o   o...o
        o....   o....   o....   o....   o....   o....   o...S   o...E

          d       m       r       d       d       d       d       l

mml네 번째 글 머리 기호를 완성하는 마지막 글은 모든 문자에 나타나고 위에서 제안한 솔루션의 모든 항목에 다시 두 개의 열을 추가하고 싶지 않기 때문에 암시 적입니다.

따라서 한 가지 해결책 Apddrdddammmrdmrdddmrddddlmml입니다.

이것이 귀하의 솔루션 일 필요는 없습니다. 알고리즘은 모든 열을 통과하여 신호음을 적절한 위치에 배치하고 다른 신호음이 배치되거나 배치되는 위치에 의존하지 않습니다. 알고리즘이 무엇이든 로봇은 그리드의 공간 당 하나의 신호음을 배치 할 수 있습니다.


프로그램

프로그램은 문자의 그리드가 무엇인지 5xN 그리드로 입력합니다. 입력에는 로봇이 없습니다. 로봇은 북쪽을 향한 왼쪽 하단 (남서쪽) 모서리에있는 것으로 가정합니다.

출력은 시퀀스의 속기 문자 시퀀스입니다.

샘플 입력

.ooo.
o...o
ooooo
o...o
o...o

o...o.ooooo
o...o...o..
ooooo...o..
o...o...o..
o...o.ooooo

샘플 출력

pddrdddammmrdmrdddmrddddlmml

prmmmlmlmmdrdrdddlmlmmdrdrmmmdrddddlmmlprdddlmldmmrmrmdmlmldmmrdrddddrmmmdlmml

이것은 코드 골프입니다. 표준 CG 규칙이 적용됩니다. 바이트 단위의 최단 코드가 이깁니다.


보너스 라운드

규칙

보너스 라운드에 참여하려면 코드를 효율적으로 이동하십시오! 아래는 내 프로그램이 실행될 때 만드는 5x5 글자 모두의 라이브러리입니다. 보너스 라운드의 목표는 ABCDEFGHIJKLMNOPQRSTUVWXYZ가능한 적은 움직임을 포함 하는 시퀀스를 인쇄하는 프로그램을 작성하는 것 입니다. STDIN에 입력이 없습니다. 코드 채점 것 없는 코드의 길이에 그러나 그것의 "이동 점수." 이동 점수는 사각형의 모든 지점을 방문하는 스위퍼 알고리즘을 사용하지 않도록 설계되었습니다.

d: 1
l: 1
m: 4
p: 1
r: 1

편지

.ooo.   oooo.   ooooo   oooo.   ooooo   ooooo   .oooo   o...o
o...o   o...o   o....   o...o   o....   o....   o....   o...o
ooooo   oooo.   o....   o...o   oooo    oooo.   o.ooo   ooooo
o...o   o...o   o....   o...o   o....   o....   o...o   o...o
o...o   oooo.   ooooo   oooo.   ooooo   o....   oooo.   o...o

ooooo   ....o   o...o   o....   ooooo   o...o   ooooo   oooo.
..o..   ....o   o..o.   o....   o.o.o   oo..o   o...o   o...o
..o..   ....o   oo...   o....   o.o.o   o.o.o   o...o   oooo.
..o..   o...o   o..o.   o....   o...o   o..oo   o...o   o....
ooooo   .ooo.   o...o   ooooo   o...o   o...o   ooooo   o....

oooo.   oooo.   ooooo   ooooo   o...o   o...o   o...o   o...o
o..o.   o...o   o....   ..o..   o...o   o...o   o...o   .o.o.
o..o.   oooo.   ooooo   ..o..   o...o   .o.o.   o.o.o   ..o..
oooo.   o..o.   ....o   ..o..   o...o   .o.o.   o.o.o   .o.o.
....o   o...o   ooooo   ..o..   ooooo   ..o..   ooooo   o...o

o...o   ooooo
.o.o.   ...o.
..o..   ..o..
.o...   .o...
o....   ooooo

원래의 도전과 동일한 절차를 따라야합니다. 각 문자 사이에 공백을두고 한 번에 하나씩 문자를 그려야합니다.

표준 CG 규칙이 적용됩니다. 이동 점수가 가장 낮은 항목이 이깁니다.




요약하면 두 코드 모두 본질적으로 동일한 작업을 수행합니다. 첫 번째 코드는 코드에서 최소 바이트 수를 가져야하고 두 번째 코드는 가장 적은 수의 이동을 사용해야합니다.


깔끔한 도전-왜 당신이 downvoted되고 있는지 모릅니다.
Deusovi

1
감사합니다 @Deusovi. 나는 그들이 이해가되지 않거나 그것을 향상시키지 않는 것을 정리할 수 있도록 이유를 설명하기를 바랍니다.
Arcturus

" Karel (로봇)은 5 가지 동작 만 수행합니다 ." 능력 이 없다 "고 생각 하고 5 번째 동작이 빠진 것 같습니다. 그리고 보너스 라운드가 무엇인지 잘 모르겠습니다. 최고의 솔루션을 작성한 사람에게 현상금을 수여 하시겠습니까?
피터 테일러

아마도 코드 골프 도전 대신에 최소한의 골프 도전으로 바꾸는가? 이것은 효율성에 관한 것입니다.
LukStorms

1
코드 골프 부분이 없으면 움직임이 제한되어있는 최소한의 이동 문제는 그리 흥미롭지 않습니다. 최적의 경로를 BFS하는 것은 매우 쉽습니다.
bopjesvla

답변:


5

perl -p0, 60 56 54 + 2 바이트

골프

/
/;$:="m"x"@-";$_=mmmmlma.s/
/rmr$:a/gr.mml;y/.o/md/;

노트

/\n/; # capture the length of the first line
$:="m"x"@-"; # assign a string of m's with that length to $:
s/^/mmmmlmll/; # move to the starting position (-1,0)
s/\n/rmr$:rr/g; # replace all newlines with kareliage returns
y/.o/md/; # replace dots with moves and o's with drops
s/$/mml/; # append mml

의 좋은 사용 @-, 질문 골프 팁에 공유하는 유용한 하나가 될 수 있습니다 !
Dom Hastings

2

자바 스크립트 (ES6), 91

첫 번째 기본 도전을 시도하십시오.

EcmaScript 6 호환 브라우저 (Firefox에서 테스트)에서 아래 스 니펫 실행 테스트

보너스 도전 답변-전체 알파벳 점수 = 869

Firefox에서 아래 스 니펫 실행 테스트 (전체 화면)

고정 입력 / 고정 출력 문제가 마음에 들지 않으므로 입력 을 시도 할 수 있습니다. 문자 만 인쇄됩니다.

// Optimal - working on small pattern but too slow (scale bad)
// So I build the total command letter by letter - that surely is NOT globally optimal

Key=sol=>sol.pos+' '+sol.setBits

Solve=(target, startRow, startDir, cmd)=>{
  // Target is a rectangle string 5x5, newline separated for total (5+1)*5 chars
  if (target[target.length-1] != '\n') target += '\n';
  
  var T = ~new Date()
  var width = 5, height = 5, startPos = (width+1)*startRow;
  var offset = [-width-1, 1, width+1, -1];
  var turns = [ "", "r", "rr", "l" ];
  var cmds = [ "m", "rm", "rrm", "lm", "d", "rd", "rrd", "ld" ];
  var visited = {}, scan =[[],[],[],[],[],[],[],[]], cscan;
  
  var baseSol = { steps:[], pos: startPos, dir: startDir, setBits: 0};
  var score = 0, j = 0
  var bit, key, turn, curSol, move, result
  var targetBits = 0; 
  [...target].map((c,i)=>targetBits |= ((c=='o')<<i)) // 30 bits
  
  // First step, from outside, set bit in mask if it's set in target
  if (target[startPos]=='o') baseSol.setBits = 1<<startPos;
  console.log(target, targetBits.toString(16))
  visited[Key(baseSol)] = scan[0].push(baseSol);
  

  for (j = 0; j<99; j++)
  {
     cscan = scan[j];
     scan.push([])
     
     // console.log(`T: ${T-~new Date} J: ${j} SC: ${cscan.length}`)
     while (cscan.length > 0)
     {
        baseSol = cscan.pop()
        //console.log('Base', baseSol.dir, baseSol.pos, baseSol.setBits.toString(16), baseSol.steps.length)
        for(turn = 0; turn < 4; turn++)
        {
           // set direction, move and drop if you can
           curSol = {};
           curSol.dir = baseSol.dir + turn & 3;
           curSol.pos = baseSol.pos + offset[curSol.dir];
           // console.log(turn, curSol.dir, curSol.pos)
           if(target[curSol.pos] > ' '
              || curSol.dir == 1 && target[curSol.pos]=='\n'
             ) // if inside grid or on right border facing east
           {
              score = j + (turn == 2 ? 3 : turn == 0 ? 1 : 2);
              bit = 1 << curSol.pos;
              if (targetBits & bit)
                 curSol.setBits = baseSol.setBits | bit, move = 4 | turn;
              else
                 curSol.setBits = baseSol.setBits, score += 3, move = turn;
              if (!visited[key = Key(curSol)]) 
              {
                 curSol.steps = [...baseSol.steps, move] // clone and add
                 // task completed if on  right border and all bits ok
                 if (target[curSol.pos]>' ')
                 { // not on right border, proceed  
                    visited[key] = scan[score].push(curSol)
                 }  
                 else if (curSol.setBits == targetBits)
                 {
                    result = curSol.steps.map(v=>cmds[v]).join``
                    result = (cmd == '' 
                    ? target[startPos]=='o' ? 'p' : '' 
                    : target[startPos]=='o' ? 'd' : 'm') + result;
                    console.log(`T: ${T-~new Date} J: ${j} CMD: ${result}`)
                    return [cmd+result, curSol.pos / (width+1) | 0];
                 }
              }
           }
        }
     }
  }
  // Miserable failure!
  return []
}  

console.log=(...x)=>LOG.innerHTML+=x+'\n';
// TEST
Karel=(cmd, width, height) =>  // even if for this test we have a limited height to handle
{ 
  var grid = [...('.'.repeat(width)+'\n').repeat(height)],
  o = width+1,p = o*(height-2)+1,d = [-o, 1, o, -1], // direction offsets
  steps = [],s = [...grid],q = 0; // face up

  s[p] = 'n';
  steps.push([s.join``,'-']);
  
  [...cmd].forEach(c => 
    (
      c == 'l' ? q = q-1 &3
      : c == 'r' ? q = q+1 &3
      : c == 'a' ? q = q+2 &3
      : c == 'm' ? p += d[q]
      : c == 'p' ? grid[p] = 'o'
      : c == 'd' ? grid[p += d[q]] = 'o'
      : 0,
      s = [...grid],  
      s[p] = s[p] == 'o' ? 'NESW'[q] : 'nesw'[q],
      steps.push([s.join``,c])
    )
  )
  return [s.join``,steps]
}  


var AlphabetMap = `.ooo..oooo..ooooo.oooo..ooooo.ooooo..oooo.o...o.ooooo.....o.o...o.o.....ooooo.o...o.ooooo.oooo..oooo..oooo..ooooo.ooooo.o...o.o...o.o...o.o...o.o...o.ooooo
o...o.o...o.o.....o...o.o.....o.....o.....o...o...o.......o.o..o..o.....o.o.o.oo..o.o...o.o...o.o..o..o...o.o.......o...o...o.o...o.o...o..o.o...o.o.....o.
ooooo.oooo..o.....o...o.oooo..oooo..o.ooo.ooooo...o.......o.oo....o.....o.o.o.o.o.o.o...o.oooo..o..o..oooo..ooooo...o...o...o..o.o..o.o.o...o.....o.....o..
o...o.o...o.o.....o...o.o.....o.....o...o.o...o...o...o...o.o..o..o.....o...o.o..oo.o...o.o.....oooo..o..o......o...o...o...o..o.o..o.o.o..o.o...o.....o...
o...o.oooo..ooooo.oooo..ooooo.o.....oooo..o...o.ooooo..ooo..o...o.ooooo.o...o.o...o.ooooo.o.........o.o...o.ooooo...o...ooooo...o...ooooo.o...o.o.....ooooo`.split('\n')
var LetterMap = [];
var l,row,m;

for (l=0;l<26;l++)
{
  for(m='',row=0;row<5;row++)
    m += AlphabetMap[row].substr(l*6,5)+'\n'
  LetterMap[l]=m;  
}

print=Message=>{
  var Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  var startRow = 4, cmd=''
  var startDir = 0 // start facing UP
  ;[...Message].forEach(l => (
    [cmd, startRow] = Solve(LetterMap[Alphabet.search(l)], startRow, startDir, cmd),
    startDir = 1, // after each letter will be facing RIGHT
    cmd += '\n' // addin a newline (scoring 0) just for readability
  ))

  if (startRow != 4) 
    cmd += 'mr'+'m'.repeat(4-startRow)+'rr' // on last row and facing up
  else 
    cmd += 'ml' // ...facing up

  // Recalc score
  var score = 0
  ;[...cmd].forEach(c=>score += c=='m'? 4 : c<' '? 0: 1)

  var robot = Karel(cmd.replace(/\n/g,''), 26*7, 7)
  O.innerHTML=cmd+'\nScore:'+score
  R.innerHTML=robot[0]
  RS.innerHTML=robot[1].join`\n`
}  

function test()
{
  var msg = I.value.toUpperCase()
  msg=msg.replace(/[^A-Z]/g,'')
  I.value=msg
  print(I.value)
}

test()
fieldset {
  padding:0;
}

pre {
  margin: 2px;
}

#RS {
  height: 200px;
  width: 50%;
  overflow:auto;
}

#I { width: 50% }
<fieldset ><legend>Message to print</legend>
<input id=I value='ABCDEFGHIJKLMNOPQRSTUVWXYZ'><button onclick='test()'>go</button></fieldset>
<fieldset ><legend>Command Result (newlines added for readability)</legend>
<pre id=O></pre></fieldset>
<fieldset ><legend>Robot output</legend>
<pre id=R></pre></fieldset>
<fieldset ><legend>Robot step by step</legend>
<pre id=RS></pre></fieldset>
<fieldset ><legend>log</legend>
<pre id=LOG></pre></fieldset>


보너스는 어떻습니까?
Arcturus

@Eridan 보너스는 잘 가고 있습니다. 불행히도 나도 직업이있다 : :)
edc65

확인! 난 당신을 비난하지 않습니다. 당신은 보너스를 시도한 유일한 사람입니다.
Arcturus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.