Karel J. AlphaBot Sequence Generator


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

Karel J. AlphaBot

พื้นหลัง

หลักสูตรเบื้องต้นยอดนิยมสำหรับ Java คือKarel J. Robot (ฉันใช้เอง) หุ่นยนต์โต้ตอบกับตารางของถนน (จำนวนเต็มบวก y- พิกัด) และลู่ทาง (บวก x จำนวนเต็มพิกัด) พร้อมกับบี๊บซึ่งสามารถวางและเก็บไว้ในตารางได้ (โปรดทราบว่าคาเรลและบี๊บใด ๆ สามารถอยู่บนตาข่ายได้เท่านั้น คะแนน) Karel (หุ่นยนต์) เพียงเพื่อดำเนินการห้าประการ: เดินหน้าต่อไป 1 เลี้ยวซ้ายเข้าที่วาง beeper หยิบ beeper แล้วปิดตัวเอง

ในวิชาวิทยาการคอมพิวเตอร์หนึ่งในงานมอบหมายชิ้นแรกของเราคือการเขียนโปรแกรมให้คาเรลเพื่อเรียนรู้วิธีเลี้ยวขวาเลี้ยวไปรอบ ๆ และปฏิบัติงานร่วมกันของการก้าวไปข้างหน้าโดย 1 และวางบี๊บลง การมอบหมายไม่กี่วันต่อมาคือการใช้วิธีการเหล่านี้และเขียนวิธีการใหม่เพื่อผลิตตัวอักษรของตัวอักษร

เมื่อฉันทำภารกิจนี้เสร็จฉันก็เขียนวิธีการเพิ่มเติมเพื่อทำตัวอักษรทุกตัวรวมถึงตัวเลขสิบหลักและฉันวางแผนที่จะหาวิธีสร้างตัวประมวลผลคำจากหุ่นยนต์โดยที่สตริง จะถูกป้อนไปยัง STDIN และหุ่นยนต์จะส่งเสียงบี๊บบนกริดในลักษณะที่คล้ายกับตัวอักษร

ทุกครั้งที่ฉันเขียนprivate void draw#ให้กับตัวละครแต่ละตัว#ฉันเพิ่มความคิดเห็นหลังจากนั้นมันจะบอกตัวย่อสำหรับลำดับของคำสั่งที่ฉันต้องการ

ฉันมีคำสั่งต่อไปนี้ (เขียนเป็น pseudocode) ตามคำสั่งของฉัน (ชี้แจง - นี่เป็นคำสั่งที่มีประโยชน์เท่านั้น)

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 ของพื้นที่ขนาดเล็กที่ตัวอักษรจะถูกวาด
  • หุ่นยนต์ดึงตัวอักษร
  • หุ่นยนต์เคลื่อนที่ไปที่มุมขวาล่างของสี่เหลี่ยม
  • หุ่นยนต์เคลื่อนที่สองช่องว่างไปทางขวาและจะต้องหันไปทางทิศเหนือ / ขึ้น

ลองทำตัวอย่าง Aสมมติว่าเราต้องการที่จะดึง ตำแหน่งของหุ่นยนต์คือตัวอักษรที่บอกทิศทางของมัน (เหนือ, ใต้, ตะวันออก, ตะวันตก) ตัวอักษรจะเป็นตัวพิมพ์ใหญ่หากหุ่นยนต์อยู่ในตำแหน่งที่มีเสียงบี๊บและตัวพิมพ์เล็กหากหุ่นยนต์อยู่ในตำแหน่งที่ไม่มีเสียงบี๊บ oแสดงถึงจุดที่มี beepers และ.เป็นจุดที่ไม่มี beepers

อย่างที่เราจะเห็นในภายหลัง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

โปรดทราบว่านี่ไม่จำเป็นต้องเป็นทางออกของคุณ อัลกอริทึมของคุณสามารถผ่านทุกคอลัมน์วาง beepers ในตำแหน่งที่เหมาะสมและไม่พึ่งพาที่ beepers อื่น ๆ ถูกวางหรือจะวาง ไม่ว่าอัลกอริทึมของคุณจะเป็นอะไรหุ่นยนต์สามารถส่งเสียงบี๊บเดียวต่อหนึ่งช่องว่างบนกริด


โปรแกรม

โปรแกรมของคุณจะใช้เป็นอินพุทของกริด 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

นี่คือรหัสกอล์ฟ, fellas ใช้กฎ 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 มาตรฐาน รายการที่มีคะแนนการย้ายต่ำที่สุดชนะ




เพื่อสรุปรหัสทั้งสองจะทำสิ่งเดียวกัน รหัสแรกควรมีจำนวนไบต์น้อยที่สุดในรหัสและรหัสที่สองควรใช้จำนวนการเคลื่อนไหวน้อยที่สุด


ความท้าทายที่ดี - ไม่ทราบว่าทำไมคุณถึงถูกลดระดับลง
Deusovi

1
ขอบคุณ @Deusovi ฉันหวังว่าพวกเขาจะอธิบายว่าทำไมฉันจึงสามารถล้างสิ่งที่ไม่สมเหตุสมผลหรือปรับปรุงได้
Arcturus

" Karel (หุ่นยนต์) มีไว้เพื่อทำงานห้าอย่างเท่านั้น ": ฉันคิดว่าคุณขาด " สามารถ " และคุณพลาดการกระทำที่ห้าไปแน่นอน และฉันไม่แน่ใจว่ารอบโบนัสคืออะไร: คุณจะให้รางวัลแก่ผู้ที่เขียนทางออกที่ดีที่สุดหรือไม่?
Peter Taylor

บางทีแทนที่จะเป็นรหัสความท้าทายกอล์ฟเปลี่ยนเป็นความท้าทายกอล์ฟย้ายน้อยที่สุด? ตั้งแต่นี้เป็นเรื่องเกี่ยวกับประสิทธิภาพ
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

การใช้งานที่ดี@-อาจเป็นประโยชน์อย่างหนึ่งในการแบ่งปันเคล็ดลับสำหรับการเล่นกอล์ฟในคำถามPerl !
Dom Hastings

2

JavaScript (ES6), 91

ความพยายามครั้งแรกกับความท้าทายพื้นฐาน

ทดสอบการเรียกใช้ตัวอย่างข้อมูลด้านล่างในเบราว์เซอร์ที่สอดคล้องกับ EcmaScript 6 (ทดสอบใน Firefox)

คำตอบโบนัสท้าทาย - คะแนนสำหรับตัวอักษรเต็ม = 869

ทดสอบการเรียกใช้ wnippet ด้านล่างใน 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.