Parser pliku kostnicy DCSS

9

W tym wyzwaniu musisz przeanalizować pliki kostnicy z roguelike gry Dungeon Crawl Stone Soup i wysłać ją do STDOUT.

Co to za pliki kostnicy?

Po śmierci generowany jest plik tekstowy z danymi tego znaku. Możesz zobaczyć, jakie wyposażenie posiadał bohater, co wydarzyło się w ciągu ostatnich kilku tur i ile potworów zabił.

Przykładowy plik kostnicy można znaleźć tutaj

Wyzwanie

Twoim zadaniem jest stworzenie programu, który pobierze jeden z tych plików ze STDIN, przeanalizuje go i wyśle ​​dane do STDOUT.

Aby to wyzwanie było trochę łatwiejsze, musisz przeanalizować tylko pierwszy blok tekstu. (aż doThe game lasted <time> (<turns> turns).

Musisz przeanalizować i wydrukować następujące informacje:

  • Numer wersji.
  • Wynik.
  • Nazwa postaci, tytuł, rasa i klasa.
  • Poziom postaci.
  • Przyczyna śmierci / zwycięstwa.
  • Liczba obrotów trwała bieg.

Przykład:

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).

Przypadki testowe

Przypadek testowy 1 - zwycięstwo

Plik wejściowy

Przykładowy wynik - Zwycięstwo:

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

Przypadek testowy 2 - śmierć

Plik wejściowy

Przykładowy wynik - Śmierć:

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

Zasady

  • To jest więc wygrywa najkrótszy kod.
  • W przypadku remisu wygrywa najstarsza odpowiedź.
  • Brak standardowych luk.
  • Dane wejściowe pliku należy pobrać ze STDIN
  • Dane wyjściowe należy wysłać do STDOUT
  • Etykiety przed wyjściem (np. Turns:) Są opcjonalne.

Nieprzygotowany przykładowy kod dla inspiracji

Kod generowania pliku kostnicy w DCSS

DJgamer98
źródło
Czy dane wyjściowe faktycznie muszą zawierać etykiety linii takie jak Version:lub wystarczają do wydrukowania informacji w tej samej kolejności, po jednej w wierszu?
Martin Ender
@ MartinBüttner Etykiety są opcjonalne.
DJgamer98
Czy rasa i klasa zawsze będą jednym słowem?
Martin Ender
@ MartinBüttner Niektóre rasy i klasy to dwa słowa, takie jak Vine Stalker, Abyssal Knight i Deep Elf.
DJgamer98
2
Czy istnieje specyfikacja tego formatu pliku kostnicy, czy tylko te przykłady?
Paŭlo Ebermann

Odpowiedzi:

3

Perl, 151 bajtów

Kod 148 + 3 przełączniki ( -0, -l, -p). Jestem pewien, że można to poprawić :)

Pobiera dane wejściowe ze STDIN i drukuje wynik po otrzymaniu 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]'

Nie golfowany:

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

svsd
źródło
3

F #, 377 bajtów

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")
odpływ
źródło
3

JavaScript (ES6), 297 230 bajtów

Na razie jest to wyrażenie regularne sterowane testem.

Po prostu zastępuje niechciane informacje i zachowuje ważne rzeczy.

Tworzy anonimową funkcję, która po prostu zwraca poszukiwany tekst.

_=>_.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} ?)?/,' ')

Czy to nie jest bestia?


Dzięki za wskazówkę sysreq na temat opcjonalności etykiet. To zaoszczędziło mi 67 bajtów !


Możesz przetestować wyrażenie resulgar na: https://regex101.com/r/zY0sQ0/1

Ismael Miguel
źródło
Etykiety są opcjonalne; możesz zaoszczędzić sporo bajtów, pomijając je.
kot
1
@sysreq Co ...?
Ismael Miguel
2
Mówię, że _=>_.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} ?)?/,' ')jest to akceptowalne rozwiązanie przy zaledwie 230 bajtach
cat
1
@sysreq Przepraszam, że tak długo nic mówię. Widziałem post, ale byłem na tablecie. Nie masz pojęcia, jak bolesne jest robienie czegokolwiek na tablecie. Zamieniłem mój kod na wersję bez etykiet. Wielkie dzięki za wskazówkę.
Ismael Miguel
2

Python3, 472 bajtów

Myślałem, że będę w stanie być o wiele krótszy. Jednak nie jestem zaskoczony, że pokonałem własne zdanie. Uruchom to jak 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))
kot
źródło
2

Idź, 589 502 489 487 bajtów

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))}

po uruchomieniu go fmt, go fixa go vettutaj jest wersja „bez golfa”:

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))
}

Edytować: użycie importu kropkowego bardzo pomaga.

Dość oczywiste, ale w razie potrzeby mogę wyjaśnić. To mój pierwszy „prawdziwy” program Go i wciąż jestem początkującym w codegolf, więc napiwki są mile widziane!

Edycja: powiedziałeś „weź plik ze STDIN” i możesz uruchomić ten skrypt (jeśli masz zainstalowany), uruchamiając, go install <foldername>a następnie <binaryname> morgue-file.txtlubgo run main.go morgue.txt

kot
źródło