Last active
December 9, 2018 07:36
-
-
Save watr/c87534531b51a8f2d629c02ee4776a07 to your computer and use it in GitHub Desktop.
横浜へなちょこプログラミング勉強会 #yhpg https://yhpg.doorkeeper.jp/ アンエスケープ 2018.12.8 http://nabetani.sakura.ne.jp/hena/orde29unes/ をSwift(4.2)で解いた
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 横浜へなちょこプログラミング勉強会 | Doorkeeper | |
// https://yhpg.doorkeeper.jp/ | |
// | |
// アンエスケープ 2018.12.8 | |
// http://nabetani.sakura.ne.jp/hena/orde29unes/ | |
import Foundation | |
var tested_count = 0 | |
var ok_count = 0 | |
var ng_count = 0 | |
enum ParseOperation { | |
case skip | |
case add | |
case split | |
} | |
enum ParseError: Error { | |
case quotationNotClosed | |
case hasEmptyItem | |
} | |
func parse(text: String) throws -> [String] { | |
var result: [String] = [] | |
var pending: String = "" | |
var quote: Character? = nil | |
func append() throws { | |
guard pending.count > 0 else { | |
throw ParseError.hasEmptyItem | |
} | |
result.append(pending) | |
pending = "" | |
} | |
func atLast() throws { | |
let valid = (quote == nil) | |
guard valid else { | |
throw ParseError.quotationNotClosed | |
} | |
try append() | |
} | |
let characters = text.map({ Character(String($0)) }) | |
var i = 0 | |
while i < characters.count { | |
let c = characters[i] | |
let o: ParseOperation | |
if quote != nil { | |
if quote! == c { | |
quote = nil | |
o = .skip | |
} | |
else { | |
o = .add | |
} | |
} | |
else { | |
switch c { | |
case "/": | |
let nexti = (i + 1) | |
if ((nexti < characters.count) && | |
(characters[nexti] == "/")) | |
{ | |
o = .add | |
i += 1 | |
} | |
else { | |
o = .split | |
} | |
case "\"", "\'":// quotation has not begun, begin quotation | |
quote = c | |
o = .skip | |
default: | |
o = .add | |
} | |
} | |
switch o { | |
case .skip: | |
break | |
case .add: | |
pending.append(c) | |
case .split: | |
try append() | |
} | |
i += 1 | |
} | |
try atLast() | |
return result | |
} | |
func solve(input: String) -> String { | |
if let parsed = try? parse(text: input) { | |
return parsed.joined(separator: ",") | |
} | |
else { | |
return "-" | |
} | |
} | |
func test(_ input: String, _ expected: String, skips: Bool = false) { | |
if skips { | |
return | |
} | |
let answer = solve(input: input) | |
if answer == expected { | |
ok_count += 1 | |
} | |
else { | |
ng_count += 1 | |
print("test \(tested_count) FAILED.") | |
print(" input: \(input)") | |
print("expected: \(expected)") | |
print(" actual: \(answer)") | |
print() | |
} | |
tested_count += 1 | |
} | |
/*0*/ test( "foo/bar/baz", "foo,bar,baz" ); | |
/*1*/ test( "/foo/bar/baz'/", "-" ); | |
/*2*/ test( "\"", "-" ); | |
/*3*/ test( "'", "-" ); | |
/*4*/ test( "/", "-" ); | |
/*5*/ test( "\"\"", "-" ); | |
/*6*/ test( "''", "-" ); | |
/*7*/ test( "//", "/" ); | |
/*8*/ test( "\"/'", "-" ); | |
/*9*/ test( "'/\"", "-" ); | |
/*10*/ test( "Qux", "Qux" ); | |
/*11*/ test( "Foo/Bar", "Foo,Bar" ); | |
/*12*/ test( "foo\"bar", "-" ); | |
/*13*/ test( "foo'bar", "-" ); | |
/*14*/ test( "/foo/bar", "-" ); | |
/*15*/ test( "Foo//Bar", "Foo/Bar" ); | |
/*16*/ test( "foo/bar/", "-" ); | |
/*17*/ test( "'\"'a'\"'/b", "\"a\",b" ); | |
/*18*/ test( "Foo\"/\"Bar", "Foo/Bar" ); | |
/*19*/ test( "foo\"'\"bar", "foo'bar" ); | |
/*20*/ test( "foo'\"'bar", "foo\"bar" ); | |
/*21*/ test( "foo///bar", "foo/,bar" ); | |
/*22*/ test( "\"Z\"\"tO\"uFM", "ZtOuFM" ); | |
/*23*/ test( "''/foo/bar", "-" ); | |
/*24*/ test( "////'/\"//'", "///\"//" ); | |
/*25*/ test( "File/'I/O'", "File,I/O" ); | |
/*26*/ test( "Foo'//'Bar", "Foo//Bar" ); | |
/*27*/ test( "foo/''/bar", "-" ); | |
/*28*/ test( "foo/bar/\"\"", "-" ); | |
/*29*/ test( "'/////'////", "///////" ); | |
/*30*/ test( "'foo\"\"\"bar'", "foo\"\"\"bar" ); | |
/*31*/ test( "//'int'/V/c", "/int,V,c" ); | |
/*32*/ test( "foo/bar/baz", "foo,bar,baz" ); | |
/*33*/ test( "'H//Sg//zN'/", "-" ); | |
/*34*/ test( "//'//\"/'/'\"'", "///\"/,\"" ); | |
/*35*/ test( "foo//bar/baz", "foo/bar,baz" ); | |
/*36*/ test( "\"\"\"///\"/'/'//", "///,//" ); | |
/*37*/ test( "58\"\"N\"//nIk'd", "-" ); | |
/*38*/ test( "foo\"/\"bar/baz", "foo/bar,baz" ); | |
/*39*/ test( "/////'\"/'/'\"/'", "//,\"/,\"/" ); | |
/*40*/ test( "f\"//J\"/O9o\"//'", "-" ); | |
/*41*/ test( "foo\"//\"bar/baz", "foo//bar,baz" ); | |
/*42*/ test( "foo/bar////baz", "foo,bar//baz" ); | |
/*43*/ test( "\"\"\"'/'//'''/\"//", "'/'//'''//" ); | |
/*44*/ test( "8//'/k///\"3da\"'", "8//k///\"3da\"" ); | |
/*45*/ test( "foo/'/bar/'/baz", "foo,/bar/,baz" ); | |
/*46*/ test( "///''\"//\"\"///\"\"\"", "/,/////" ); | |
/*47*/ test( "//wUJ8KNAk'n0//\"", "-" ); | |
/*48*/ test( "What/is/'\"real\"'", "What,is,\"real\"" ); | |
/*49*/ test( "\"//'/////\"''/'//'", "//'/////,//" ); | |
/*50*/ test( "\"8hKE\"3Fx/4//Hk/J", "8hKE3Fx,4/Hk,J" ); | |
/*51*/ test( "'////''\"'//'/\"///'", "////\"//\"///" ); | |
/*52*/ test( "Ro\"/j''/2u/f/r/\"3n", "Ro/j''/2u/f/r/3n" ); | |
/*53*/ test( "hoge\"//\"fuga//piyo", "hoge//fuga/piyo" ); | |
/*54*/ test( "'foo//bar'//baz/qux", "foo//bar/baz,qux" ); | |
/*55*/ test( "//'//\"'/\"///'\"/''//", "///\",///',/" ); | |
/*56*/ test( "2/L'3'A8p/7//wP49Jb", "2,L3A8p,7/wP49Jb" ); | |
/*57*/ test( "\"foo'\"/\"bar'\"/\"baz'\"", "foo',bar',baz'" ); | |
/*58*/ test( "'//'\"//'///'///''\"//", "////'///'///''/" ); | |
/*59*/ test( "F6vX/q/Zu//5/'/H\"/'w", "F6vX,q,Zu/5,/H\"/w" ); | |
/*60*/ test( "\"foo'bar\"/'hoge\"fuga'", "foo'bar,hoge\"fuga" ); | |
/*61*/ test( "/\"/'//'/\"\"\"''//'/\"'''", "-" ); | |
/*62*/ test( "0gK\"koYUb\"\"S/p''z/\"Et", "0gKkoYUbS/p''z/Et" ); | |
/*63*/ test( "Foo/Bar/\"Hoge'/'Fuga\"", "Foo,Bar,Hoge'/'Fuga" ); | |
print("total test count: \(tested_count)") | |
print(" ok count: \(ok_count)") | |
print(" ng count: \(ng_count)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment