โปรแกรมแยกวิเคราะห์ไฟล์ DCSS


9

ในการท้าทายนี้คุณจะต้องแยกวิเคราะห์ไฟล์จากเกมโร๊คไลค์Dungeon คลานหินซุปแล้วส่งไปที่ STDOUT

ไฟล์โรงเก็บศพเหล่านี้คืออะไร?

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

คุณสามารถหาไฟล์ตัวอย่างโรงเก็บศพได้ที่นี่

ความท้าทาย

งานของคุณคือการสร้างโปรแกรมที่ใช้ไฟล์ใดไฟล์หนึ่งจาก STDIN แยกวิเคราะห์และส่งออกข้อมูลไปยัง STDOUT

เพื่อให้การท้าทายนี้ง่ายขึ้นคุณต้องแยกวิเคราะห์ข้อความแรก (จนถึงThe game lasted <time> (<turns> turns).

คุณต้องแยกวิเคราะห์และส่งออกข้อมูลต่อไปนี้:

  • หมายเลขรุ่น
  • คะแนน.
  • ชื่อตัวละครชื่อการแข่งขันและคลาส
  • ระดับตัวละคร
  • สาเหตุของการเสียชีวิต / ชัยชนะ
  • จำนวนรอบการหมุนของการวิ่งกินเวลา

ตัวอย่าง:

Dungeon Crawl Stone Soup version <version number> character file.

<score> <name> the <title> (level <level>, 224/224 HPs)
         Began as a <race> <class> on Mar 16, 2015.
         Was the Champion of the Shining One.
         <cause of death/victory>

         The game lasted 16:11:01 (<turns> turns).

กรณีทดสอบ

กรณีทดสอบ 1 - ชัยชนะ

ใส่ไฟล์

ตัวอย่างผลลัพธ์ - ชัยชนะ:

Version: 0.16.0-8-gd9ae3a8 (webtiles)
Score: 16059087
Name: Ryuzilla the Conqueror
Character: Gargoyle Berserker
Level: 27
Cause of Death/Victory: Escaped with the Orb and 15 runes on Mar 17 2015!
Turns: 97605

กรณีทดสอบ 2 - ความตาย

ใส่ไฟล์

ตัวอย่างผลลัพธ์ - ความตาย:

Version: 0.16-a0-3667-g690a316 (webtiles)
Score: 462
Name: 8Escape the Ruffian
Character: Bearkin Transmuter
Level: 6
Cause of Death/Victory: Slain by an orc wielding a +0 trident (3 damage) on level 4 of the Dungeon.
Turns: 3698

กฎระเบียบ

  • นี่คือ ดังนั้นรหัสที่สั้นที่สุดชนะ
  • ในกรณีที่เสมอกันคำตอบที่เก่าที่สุดชนะ
  • ไม่มีช่องโหว่มาตรฐาน
  • ต้องป้อนไฟล์จาก STDIN
  • ต้องส่งเอาต์พุตไปที่ STDOUT
  • เลเบลก่อนหน้าเอาต์พุต (เช่นTurns:) เป็นทางเลือก

โค้ดตัวอย่างที่ไม่ได้รับแรงบันดาลใจ

รหัสการสร้างไฟล์ที่เก็บใน DCSS


จริง ๆ แล้วผลลัพธ์ต้องประกอบด้วยป้ายชื่อของบรรทัดเช่นVersion:หรือเพียงพอที่จะเอาท์พุทชิ้นส่วนของข้อมูลในลำดับเดียวกันหนึ่งต่อบรรทัดหรือไม่
Martin Ender

@ MartinBüttnerฉลากเป็นตัวเลือก
DJgamer98

การแข่งขันและชั้นเรียนจะเป็นหนึ่งคำหรือไม่?
Martin Ender

@ MartinBüttnerการแข่งขันและคลาสบางคำมีสองคำเช่น Vine Stalker, Abyssal Knight และ Deep Elf
DJgamer98

2
มีสเปคของรูปแบบไฟล์โรงเก็บศพนี้หรือเพียงแค่ตัวอย่างเหล่านี้?
Paŭlo Ebermann

คำตอบ:


3

Perl, 151 ไบต์

148 รหัส + 3 สวิตช์ ( -0, -l, -p) ฉันแน่ใจว่าสิ่งนี้สามารถปรับปรุงได้ :)

รับอินพุตจาก STDIN และพิมพ์ผลลัพธ์เมื่อได้รับ EOF

perl -lp0e 's/\.{3}|\s/ /g;y/ //s;$_=join$\,(/(\d.*?).{15}\..(\d+).(.+?).\(.+?(\d+).+?\b(?:a|an) (.+?) o.+? ([^.!]+[.!])[^.!]*?(\d+)[^(]+\)..\3/)[0..2,4,3,5..7]'

Ungolfed:

use strict;
use warnings;

# set the input record separator to undef (the -0 switch)
$/=undef;
# read the text (the -l switch)
$_=<STDIN>;

# replace all '...' and spaces by a ' '
s/\.{3}|\s/ /g;
# squeeze all contiguous spaces into a single space
y/ //s;
# collect the captured groups into @p
my @p=
/(\d.*?).{15}\..      # version is the first string starting with a digit and ending 15 characters before the period
 (\d+).               # points is the next string with only digits
 (.+?).\(.+?          # name starts after a gap of one character
 (\d+).+?\b(?:a|an)\s # level is inside the next open paranthesis
 (.+?)\so.+?\s        # race, class occur after the 'a' or 'an' and end before ' o' i.e. (' on')
 ([^.!]+[.!])[^.!]*?  # cause of death is the a sentence ending with '.' or '!'
 (\d+)[^(]+\)..\3     # turns is the next sentence with digits within parantheses, followed by 2 characters and the player's name
/x;
$_=join"\n",@p[0..2,4,3,5..7]; # the level and race lines need to be swapped

# print the output (the -p switch)
print $_;

ideone.com


3

F #, 377 ไบต์

open System.Text.RegularExpressions
let s=System.String.IsNullOrWhiteSpace>>not
let m f=Regex.Match((f+"").Split[|'\r';'\n'|]|>Seq.filter s|>Seq.take 8|>Seq.reduce(fun a z->a+z.Trim()), ".*n (.*) c.*\.([0-9]+) (.*) \(l.* (.*),.*a (.*) o.*\.(?:(S.*)|W.*(E.*)).*.T.*\((.*) .*\).").Groups|>Seq.cast<Group>|>Seq.skip 1|>Seq.map(fun z ->z.Value)|>Seq.filter s|>Seq.iter(printfn"%s")

3

Javascript (ES6) 297 230 ไบต์

สำหรับตอนนี้นี่เป็นนิพจน์ปกติที่ขับเคลื่อนด้วยการทดสอบ

มันเพียงแทนที่ข้อมูลที่ไม่ต้องการและเก็บสิ่งที่สำคัญ

มันสร้างฟังก์ชั่นที่ไม่ระบุชื่อที่จะส่งกลับข้อความที่ต้องการ

_=>_.replace(/^.+version(.*) character file\.([\n\r]+)(\d+)([^\(]+) \([^\d]+( \d+),.+\n\s+.+as a(.+) on.+\n\s+(?:Was.+One\.\n)?((?:.|\n)+[!.])\n(?:.|\n)+\((\d+)(?:.|\n)+$/,'$1\n$3\n‌​$4\n$6\n$5\n$7\n$8').replace(/\s+(\.{3} ?)?/,' ')

มันไม่ใช่สัตว์หรือ


ขอบคุณสำหรับเคล็ดลับของsysreqเกี่ยวกับฉลากที่เป็นตัวเลือก นั่นช่วยฉันได้67 ไบต์ !


คุณสามารถทดสอบนิพจน์ resulgar ได้ที่: https://regex101.com/r/zY0sQ0/1


ฉลากเป็นตัวเลือก คุณสามารถบันทึกได้ไม่กี่ไบต์โดยละไว้
แมว

1
@sysreq อะไร ...
Ismael Miguel


2
ฉันกำลังบอกว่า_=>_.replace(/^.+version(.*) character file\.([\n\r]+)(\d+)([^\(]+) \([^\d]+( \d+),.+\n\s+.+as a(.+) on.+\n\s+(?:Was.+One\.\n)?((?:.|\n)+[!.])\n(?:.|\n)+\((\d+)(?:.|\n)+$/,'$1\n$3\n$4\n$6\n$5\n$7\n$8').replace(/\s+(\.{3} ?)?/,' ')เป็นทางออกที่ยอมรับได้ในราคาเพียง 230 ไบต์
cat

1
@sysreq ขออภัยที่ใช้เวลานานมากในการพูดอะไร ฉันเห็นโพสต์อยู่บนแท็บเล็ตแล้ว คุณไม่รู้หรอกว่ามันเจ็บปวดแค่ไหนที่จะทำอะไรในแท็บเล็ต ฉันได้แทนที่รหัสของฉันด้วยเวอร์ชันที่ไม่มีป้ายกำกับของคุณ ขอบคุณมากสำหรับคำแนะนำ
Ismael Miguel

2

Python3, 472 ไบต์

ฉันคิดว่าฉันสามารถทำให้เรื่องนี้สั้นลงได้ ไม่แปลกใจเลยที่ฉันเอาชนะการยอมแพ้ของตัวเอง เรียกใช้เหมือนpython3 dcss.py morgue-file.txtกัน

import sys
n="\n"
s=" "
f=open(sys.argv[1],'r').read().split(n)[:11]
m=range
a=len
d=","
for i in m(a(f)):
 f[i]=f[i].split(s)
 for x in m(a(f[i])):
  f[i][x]=f[i][x].strip()
h=f[0]
g=f[10]
k=f[2]
def r(j,u):
 j=list(j)
 while u in j:
  j.remove(u)
 return"".join(j)
def l(x):
 c=s
 for i in m(a(x)):
  c+=x[i]+s
 return c.strip()
print(h[6]+s+h[7]+n+k[0]+n+g[0]+s+g[1]+s+g[2]+n+r(g[3],"(")+s+r(g[4],")")+n+r(k[5],d)+n+r(l(f[4])+l(f[5])+l(f[6])+l(f[7]),".")+n+r(g[17],d))

2

ไป, 589 502 489 487 ไบต์

package main;import(."fmt";."io/ioutil";"os";."strings");func d(z,ch string)string{return Map(func(r rune)rune{if IndexRune(ch,r)<0{return r};return -1},z)};func main(){x:=Split;f,_:=ReadFile(os.Args[1]);n:="\n";l:=" ";m:=",";h:=".";q:=x(string(f),n)[:11];k:=x(q[0],l);y:=x(q[10],l);u:=x(q[2],l);g:="";for _,e:=range Fields(d(q[4],n+h)+l+d(q[5],n+h)+l+d(q[6],n+h)+l+d(q[7],n+h)){g=g+e+l};Print(k[6]+l+k[7]+n+u[0]+n+y[0]+l+y[1]+l+y[2]+n+d(y[3]+l+y[4],"()")+n+d(u[5],m)+n+g+n+d(y[17],m))}

หลังจากทำงานgo fmt, go fixและgo vetที่นี่เป็นรุ่น "ungolfed":

package main

import (
    . "fmt"
    . "io/ioutil"
    "os"
    . "strings"
)

func d(z, ch string) string {
    return Map(func(r rune) rune {
        if IndexRune(ch, r) < 0 {
            return r
        }
        return -1
    }, z)
}
func main() {
    x := Split
    f, _ := ReadFile(os.Args[1])
    n := "\n"
    l := " "
    m := ","
    h := "."
    q := x(string(f), n)[:11]
    k := x(q[0], l)
    y := x(q[10], l)
    u := x(q[2], l)
    g := ""
    for _, e := range Fields(d(q[4], n+h) + l + d(q[5], n+h) + l + d(q[6], n+h) + l + d(q[7], n+h)) {
        g = g + e + l
    }
    Print(k[6] + l + k[7] + n + u[0] + n + y[0] + l + y[1] + l + y[2] + n + d(y[3]+l+y[4], "()") + n + d(u[5], m) + n + g + n + d(y[17], m))
}

แก้ไข: การใช้จุดนำเข้าช่วยได้มาก

สวยอธิบายตนเอง แต่ฉันสามารถอธิบายได้ถ้าจำเป็นต้องเป็น นี่เป็นโปรแกรม 'ของจริง' โปรแกรมแรกของฉันและฉันยังเป็นผู้เริ่มต้นที่ codegolf ดังนั้นยินดีต้อนรับเคล็ดลับ!

แก้ไข:คุณพูดว่า "ใช้ไฟล์จาก STDIN" และคุณสามารถเรียกใช้สคริปต์นี้ (หากคุณได้ติดตั้งไปแล้ว) โดยเรียกใช้go install <foldername>แล้ว<binaryname> morgue-file.txtหรือgo run main.go morgue.txt

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