การประเมินคะแนนตามสตริงหมากรุก FEN


17

ท้าทาย

Forsyth – Edwards Notation (FEN) เป็นสัญกรณ์มาตรฐานสำหรับการอธิบายตำแหน่งกระดานเฉพาะของเกมหมากรุก ความท้าทายของคุณคือการประเมินคะแนนโดยใช้สตริง FEN นี่คือตัวอย่างของสตริง FEN:

5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8

ใช้สตริงนี้คุณสามารถคำนวณคะแนนวัสดุสำหรับแต่ละสีด้วยตารางคะแนนต่อไปนี้:

  • p / P = Pawn = 1 จุด
  • n / N = อัศวิน = 3 คะแนน
  • b / B = Bishop = 3 คะแนน
  • r / R = Rook = 5 คะแนน
  • q / Q = ราชินี = 9 คะแนน
  • k / K = King สิ่งเหล่านี้ไม่มีคะแนนเพราะตำแหน่งทางกฎหมายทุกตำแหน่งมีกษัตริย์สำหรับแต่ละด้าน

ชิ้นส่วนสีขาวถูกกำหนดโดยใช้ตัวอักษรพิมพ์ใหญ่ ("PNBRQK") ในขณะที่ชิ้นส่วนสีดำใช้ตัวพิมพ์เล็ก ("pnbrqk") สี่เหลี่ยมที่ว่างเปล่าจะถูกบันทึกโดยใช้ตัวเลข 1 ถึง 8 (จำนวนของช่องสี่เหลี่ยมที่ว่าง) และ "/" คั่นอันดับ

จากสตริง FEN ตัวอย่างเราสามารถคำนวณคะแนนวัสดุสำหรับแต่ละด้าน:

สำหรับสีดำ:

5 k 2 / ppp 5 / 4P3 / 3R3 p / 6P1 / 1K2N r 2 / PP3P2 / 8

ชิ้นส่วนสีดำทั้งหมดที่เหลืออยู่: p + p + p + p + r นี่คือทั้งหมด 9

สำหรับสีขาว:

5k2 / ppp5 / 4 P 3/3 R 3p / 6 P 1/1 K 2 N r2 / PP 3 P 2/8

ชิ้นส่วนสีขาวทั้งหมดที่เหลืออยู่: P + R + P + N + P + P + P รวมเป็น 13

คะแนนสุดท้ายจะถูกกำหนดด้วยสูตรต่อไปนี้: คะแนนสีขาว - คะแนนดำ = คะแนนสุดท้ายดังนั้นตัวอย่างเช่นคะแนนสุดท้ายจะเป็น: 13 - 9 = 4

ตัวอย่าง :

การป้อนข้อมูล:

5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8

เอาท์พุท:

4

กฎการทั้งหมดจะผลบังคับใช้ที่นี่ทางออกที่มีจำนวนไบต์น้อยที่สุดจะเป็นผู้ชนะ


วิธีการโพสต์

# Language Name, N bytes

 [code]

 [explaination, etc.]

3
ดังนั้นตำแหน่งที่แท้จริงไม่สำคัญ คุณแค่นับตัวอักษรในสตริง?
xnor

4
Nitpick: นั่นไม่ใช่สตริง FEN ที่สมบูรณ์ นอกจากนี้kr1NQQQQ / 2rNQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / K2NQQQQเป็นผู้ชนะสำหรับสีขาวด้วยสีดำที่จะย้าย? : P
Doorknob

@ xnor ใช่ฉันคิดว่าถ้าการประเมินเป็นไปตามกลยุทธ์ก็จะซับซ้อนเกินไป คุณสามารถสันนิษฐานได้ว่าอินพุตทั้งหมดเป็นตำแหน่งทางกฎหมายดังนั้นไม่ต้องกังวลกับสิ่งนั้น
Adnan

@Doorknob ใช่คะแนนเป็นเพียงวัสดุที่ใช้ในการทำให้สิ่งต่าง ๆ ง่ายขึ้น
Adnan

คำตอบ:


3

CJam, 28 27 26 bytes

0l{i32mdD%[5ZZX9]=\3%(*+}/

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

0l         e# Push a 0 (accumulator) and a line from STDIN.
{          e# For each character of that line:
  i32md    e#   Divide its code point by 32; push quotient and residue.
           e#   This serves two purposes:
           e#     1. The quotient will let us distinguish between uppercase
           e#        letters, lowercase letters and non-letters.
           e#     2. The residue will be the same for uppercase and lowercase
           e#        variants of the same letter.
  D%       e#   Take the residue modulo 13.
           e#   This maps R,N,B,P,Q -> 5,1,2,3,4
  [5ZZX9]= e#   Select the element at that index (5 ≡ 0) from [5 3 3 1 9].
  \        e#   Swap the quotient on top of the stack.
           e#   1 is digit or slash, 1 is uppercase, 2 is lowercase.
  3%(      e#   Take the quotient modulo 3 and subtract 1 from the result.
           e#   This maps 1,2,3 -> 0,1,-1.
  *+       e#   Multiply the generated integers.
  +        e#   Add the product to the accumulator.
}/         e#

5

> <> , 64 57 56 53 ไบต์

"QRBNP"013359v
$0p4}:{:v?=1l<p4+' '{-
g4v?(0:i<+
n~<;

(-7 ไบต์ด้วยแรงบันดาลใจบางส่วนจากคำตอบของ @ El'endiaStarman, -3 ไบต์ขอบคุณ @randomra)

คำอธิบาย

โปรแกรมใช้ codebox เป็นตารางการค้นหา การอยู่นอกขอบเขตทำให้ / ไม่ทำงานกับล่ามออนไลน์ดังนั้นจึงใช้ได้กับล่าม Python อย่างเป็นทางการเท่านั้น

บรรทัดแรกผลักชิ้นตามด้วยค่าชิ้น นอกจากนี้มันยังผลัก 0 เริ่มต้นเพื่อเริ่มต้นผลรวมสำหรับบรรทัดที่สาม

บรรทัดที่สองจะใส่ค่าบวกหรือลบที่เหมาะสมที่เซลล์ชิ้นส่วนที่สอดคล้องกันเช่น-1วางไว้ที่('p', 4)และ1('P', 4)ถูกวางไว้ ความยาวของสแต็กถูกตรวจสอบเพื่อให้แน่ใจว่าการวนซ้ำ 5 ครั้ง

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

บรรทัดสุดท้ายเพียงพิมพ์ผลลัพธ์


4

ทับทิม 88 ตัวอักษร

->s{s.chars.map{|c|({P:1,N:3,B:3,R:5,Q:9}[:"#{c.upcase}"]||0)*(c.ord<90?1:-1)}.inject:+}

นี่เป็นเรื่องที่น่าอึดอัดใจและน่าเกลียดและอาจเป็นวิธีที่ดีกว่า แต่ก็ดี

{foo: 'bar'}จริง ๆ แล้วไวยากรณ์ของรูบี้นั้นเป็นเพียงน้ำตาลสำหรับ{:foo => 'bar'}- มันน่ารำคาญสำหรับการเล่นกอล์ฟเพราะมันหมายความว่าฉันต้องแปลงคีย์เป็นสัญลักษณ์ก่อนที่จะใช้มันเพื่อเข้าถึงองค์ประกอบแฮช ( :"#{x}"สั้นกว่าตัวอักษรตัวหนึ่งx.to_sym)


4

Pip, 39 ไบต์

ฉันจะกลับมาเป็นผู้นำก่อนที่คำตอบของ CJam และ Pyth จะมาพร้อมกับ ...

$+Y(95<=>A_)*013359@{"KPNBRQ"@?UCa|0}Ma

รับค่าสตริง FEN เป็นอาร์กิวเมนต์บรรทัดคำสั่ง ต่อไปนี้เป็นคำอธิบายสำหรับเวอร์ชันที่ไม่ได้รับเกียรติ:

$+({(95<=>Aa)*013359@("KPNBRQ"@?UCa|0)}Ma)

   {                                  }Ma   Map this function to each character in input:
                                UCa          Uppercase version of character
                      "KPNBRQ"@?             Its index in this string, nil if not present
                                   |0        Logical or with 0 (to turn nil into 0)
              013359@(               )       Index into this number to get piece's score
          Aa                                 ASCII value of character
     95<=>                                   1 if less than 95, -1 if greater than 95
    (       )*                               Multiply by the score
$+(                                      )  Sum all scores and autoprint result

4

Perl, 44 ไบต์

#!perl -p
$\+=lc=~y/pnbrq/13359/r*(a cmp$_)for/\D/g}{

นับ Shebang เป็นหนึ่งจะถูกนำเข้าจาก stdin


ตัวอย่างการใช้งาน

$ echo 5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8 | perl fen-score.pl
4

คำอธิบาย

ชิ้นส่วนจะถูกทับศัพท์ด้วยค่าที่เกี่ยวข้อง หากชิ้นส่วนนั้นเป็นตัวพิมพ์ใหญ่ (เช่นน้อยกว่าa) จะมีการเพิ่มมูลค่าลงในผลรวมหากไม่ลบออก


3

JavaScript ES7, 79 ไบต์124 131

s=>(i=0,[for(q of s)i+={P:1,N:3,B:3,R:5,Q:9,p:-1,n:-3,b:-3,r:-5,q:-9}[q]||0],i)

สั้นที่สุดเท่าที่ฉันจะได้รับ ใช้ความเข้าใจอาร์เรย์แฟนซีเพื่อวนผ่านสตริง

คำอธิบาย

s=>(     // Define function with an argument

    i=0, // this var will store the score

    [for(q of s)   // Loops through input
      i+=          // Adds to score by...

         {P:1,...,   // Defines value of each letter
          p:-1,...}  // Negative value instead, which will subtract
         || 0        // Otherwise add 0

    ], i           // Return score

3

Minkolang 0.9 , 72 65 64 60 44 42 41 ไบต์

13359"QRBNP"m5[d3~c~$r48*+0p0p]$I[o0q+]N.

ลองที่นี่

ต้องขอขอบคุณ Sp3000 ที่ชี้ให้เห็นวิธีที่มีประสิทธิภาพมากขึ้นในการทำเช่นนี้!

คำอธิบาย

13359"QRBNP"mผลักดันให้คะแนนและตัวอักษรที่สอดคล้องกันของพวกเขาแล้วinterleaves[1,80,3,78,3,66,5,82,9,81]พวกเขาเพื่อให้รูปลักษณ์ที่สแต็คเช่นนี้ จากนั้น5[d3~c~$r48*+0p0p]ใส่คะแนนของอักขระแต่ละตัวทั้งตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ที่ตำแหน่งของมันในพื้นที่โค้ด ในที่สุด$I[o0q+]N.วนรอบอินพุตจนกว่ามันจะว่างเปล่าเพิ่มคะแนนตามที่ไป


2

CJam, 33 ไบต์

q{"PNBRQ"_el+#13359Ab_Wf*+0+=}%:+

นี่คือวิธีการค้นหาสตริงสุดยอด ลองมันออนไลน์


2

Ouroboros , 82

Ouroboros เป็น esolang ที่ฉันออกแบบในสัปดาห์นี้ ได้เวลาหมุนแล้ว!

i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!4*(4Sn1(

แต่ละบรรทัดของคำสั่งแบบ single-char 1หมายถึงงู ouroboros ซึ่งการดำเนินการจะเริ่มจากหัว (เริ่มต้น) ถึงหาง (สิ้นสุด) และวนกลับไปที่หัว (และ)คำสั่งให้คุณกินส่วนหนึ่งของหางหรือสำรอกมันจึงเปลี่ยนสิ่งที่คำสั่งที่ได้รับการดำเนินการ หากตัวชี้คำแนะนำถูกกลืนลงไปงูจะตาย (หยุดดำเนินการ) โปรแกรม Ouroboros ประกอบด้วยงูหนึ่งตัวหรือมากกว่านั้นซึ่งดำเนินการแบบขนาน งูแต่ละตัวมีสแต็คของตัวเองและยังมีสแต็กที่แชร์

1 ข้อยกเว้นหนึ่งข้อซึ่งทำให้แตกต่างจาก Ouroboros จากหลายภาษา 2D: ตัวเลขหลายหลักสามารถเขียนได้อย่างตรงไปตรงมาโดยไม่ต้องทำคณิตศาสตร์หรือกด 0 ก่อน

งู 1

งูตัวแรกอ่านตัวอักษร ( i) และตรวจสอบว่าเป็น -1 / EOF ( .1+!) หรือไม่ ถ้าเป็นเช่นนั้นมันกินหางส่วนใหญ่จนถึงและรวมถึงM( 57*()

จากนั้นงูจะสลับรหัสอักขระด้วยการนับที่อยู่เหนือสแต็ก ( \) ย้ายการนับไปยังสแต็กที่แชร์ ( m) และกลืนอักขระอื่น ( 1() ถ้ามันกลืนพวงกุญแจไปแล้วนั่นหมายความว่ามันกลืนกิน(IP ที่เปิดอยู่และตายไป มิฉะนั้นการดำเนินการโดยการย้ายนับกลับไปที่สแต็คของงู 1 สลับมันด้วยรหัสถ่านและสำรอกตัวละครที่เคยกลืนกิน ( M\1))

จากนั้นเราใช้การดำเนินการทางคณิตศาสตร์และสแต็คเพื่อสร้างคะแนนที่เหมาะสมสำหรับตัวละคร .96>ทดสอบว่ามันเป็นตัวพิมพ์เล็กหรือไม่; 32*-แปลงที่ตามมาเป็นตัวพิมพ์ใหญ่ จากนั้นยืดยาวจาก.80=ไปยัง81=9*++++แผนที่P-> 1, N-> 3และอื่น ๆ ในที่สุดก็\2*1\-*ให้คะแนนถ้าจดหมายนั้นเป็นตัวพิมพ์เล็กและ+เพิ่มลงในการนับคะแนน จากนั้นงูก็วนซ้ำแล้วอ่านตัวละครอื่น

งู 2

งูที่สองเริ่มต้นด้วยการดำเนินการไหลกลับ ( )) ซึ่งไม่ได้ทำอะไรเป็นครั้งแรกผ่าน (เพราะไม่มีอะไรถูกกลืนกินเลยและยังตั้งแต่ popping กองว่างให้0) ถัดไปก็ผลักดันให้ความยาวของสแต็คที่ใช้ร่วมกันไปยังกองของตัวเองและมีเหตุผลขัดแย้ง ( L!) สิ่งนี้จะให้1ถ้าสแต็กว่างเปล่า0มิฉะนั้น งูคูณด้วย 4 และกินว่าตัวละครหลายตัว ( 4*()

Sหากสแต็คที่ใช้ร่วมกันเป็นที่ว่างเปล่าที่นี้หมายถึงงูตอนนี้จบลงก่อน มันผลักดัน4และวนกลับไปยัง)ที่ซึ่งมันสำรอกตัวละครที่มันเพิ่งกลืนกินและเริ่มต้นใหม่อีกครั้ง

หากมีค่าในกองซ้อนที่ใช้ร่วมกันจะไม่มีการกลืนอักขระและดำเนินการต่อ งูสลับไปยังกองซ้อนที่ใช้ร่วมกันและส่งออกตัวเลขที่นั่น ( Sn); จากนั้นมันจะกลืนอักขระตัวสุดท้ายและตาย ( 1()

การประสานข้อมูล

งูสองตัวจะต้องทำข้อมูลให้ตรงกันอย่างระมัดระวังเพื่อไม่ให้มีค่าในกองซ้อนที่ใช้ร่วมกันเมื่องู 2 ทำการตรวจสอบจนกว่าจะถึงจุดสิ้นสุดการป้อนข้อมูล Snake 1 ใส่ค่าของ stack ที่แชร์กันสั้น ๆ ในแต่ละ pass through loop ดังนั้นLคำสั่งของงู 2 จะต้องไม่ถูกดำเนินการระหว่างmและMคำสั่งในงู 1 โชคดีที่งูเข้าแถวได้ดีมาก ที่สำคัญความยาวของห่วงของงู 1 (70 คำสั่ง) คือหลายวงของงู 2 (7 คำแนะนำ) ดังนั้นทั้งสองจะไม่หลุดจากกัน:

i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5
          |__|
       Danger zone

หากตัวเลขไม่ได้ผลอย่างสมบูรณ์แบบฉันจะมีงูหนึ่งหรือสองตัวที่มีช่องว่างเพื่อทำให้พวกมันอยู่ในตำแหน่งที่ต้องการ

ทั้งหมดนี้เป็นสิ่งที่ดีมาก แต่ฉันต้องการเห็นมันในทางปฏิบัติ!

นี่คือโปรแกรมข้างต้นผ่าน Stack Snippet แม้ในการปฏิบัติงาน 1,000 ครั้งต่อวินาทีมันใช้เวลาประมาณ 10 วินาทีในการคายคำตอบสำหรับตัวอย่างอินพุต - แต่มันไปถึงที่นั่น!


2

JavaScript ES6, 71

เป็นฟังก์ชั่นนิรนาม

n=>[...n].map(x=>t+=~(y='q   rnb p PBN R   Q'.search(x))?y-9|1:0,t=0)|t

2

Perl 5, 71 63 ไบต์

%a=(P,1,N,3,B,3,R,5,Q,9);$\+=$a{$_}||-$a{uc$_}for<>=~/./g;print

สิ่งนี้จะแก้ไข$\(ตัวคั่นบรรทัดสำหรับprintซึ่งเริ่มต้นเป็นเท็จ) สำหรับตัวอักษรและตัวเลขทุกตัวในสตริงที่เป็นกุญแจสำคัญของแฮชที่%aกำหนดไว้ที่จุดเริ่มต้น มันจะเพิ่มขึ้น$\ตามมูลค่าของแฮชหากตัวอักษรเป็นกุญแจตามที่เป็นอยู่ มิฉะนั้นจะเพิ่มขึ้นทีละลบค่าของแฮชหากตัวอักษรตัวพิมพ์ใหญ่เป็นคีย์ มิฉะนั้นจะเพิ่มอะไร

ขอบคุณมากสำหรับPrimo ที่ช่วยฉันแปดไบต์ (ในความคิดเห็นในคำตอบนี้)


ฉันสามารถบันทึกไบต์อื่นที่มีข้อเสนอแนะอื่นจากพรีโม่ (ขอบคุณ!): การเปลี่ยนแปลงไป$a{$_}||-$a{uc$_} $a{$_}-$a{$"^$_}แต่นั่นเป็นคำตอบที่ค่อนข้างแตกต่างจากของฉันฉันคิดว่าดังนั้นฉันจะไม่ใช้ "เครดิต" (จาก by1 ไบต์)


1

Clojure / ClojureScript, 63 ตัวอักษร

#(apply +(map{"P"1"N"3"B"3"R"5"Q"9"p"-1"n"-3"b"-3"r"-5"q"-9}%))

เขียนโดยใช้ ClojureScript REPL ก็ควรเป็น Clojure ที่ถูกต้อง ลองมันนี่ ป้อนแล้วเรียกใช้(*1 "FEN_string_here")

ตรงไปตรงมาสวย {"P"1..."q"-9}เป็นโครงสร้างข้อมูลที่แท้จริงสำหรับแผนที่ของ "P" ถึง 1, "N" ถึง 3, ฯลฯ mapใช้ฟังก์ชันเป็นอาร์กิวเมนต์แรกและโครงสร้างข้อมูลที่จะประมวลผลเป็นวินาที - ในกรณีนี้มันใช้คุณสมบัติที่ โครงสร้างข้อมูล (ตัวอักษรแผนที่) สามารถทำหน้าที่เป็นฟังก์ชั่นการเข้าถึงของตัวเอง พารามิเตอร์สตริง ( %จากฟังก์ชันแมโคร) สามารถใช้เป็นรายการของสตริงอักขระแต่ละรายการ ตัวละครใด ๆ ที่ไม่ได้อยู่ในแผนที่จะปรากฏnilในรายการผลลัพธ์ซึ่ง+จะไม่สนใจอย่างมีความสุข


1

Pyth, 25 ไบต์

-Fmsmhy/4@S5%Ck12@Gd_rBz2

สาธิต

นี่ใช้สูตรการแมปต่อไปนี้สำหรับตัวอักษรpbnrqหากkเป็นตัวอักษร:

(4 / (((chr(k) % 12) % 5) + 1) * 2 + 1

นี่คือตัวแทนของพีพีเมื่อ:

hy/4@S5%Ck12

ก่อนอื่นโปรแกรมจะสร้างรูปแบบการป้อนข้อมูลแบบตัวพิมพ์เล็กและตัวกรองสตริงสำหรับตัวอักษรตัวพิมพ์เล็กจากนั้นจึงใช้สูตรด้านบนจากนั้นนำผลรวมและลบค่าสีดำจากค่าสีขาว


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.