Last active
August 29, 2015 14:16
-
-
Save all-user/0ac0efeb7859cd1f0e4d to your computer and use it in GitHub Desktop.
CodeIQ 「中学入試から:対称軸の本数を数えよう」提出コード
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
// | |
// main.swift | |
// | |
import Foundation | |
let path = "~/Downloads/data.txt".stringByExpandingTildeInPath | |
if let data = String( | |
contentsOfFile: path, | |
encoding: NSUTF8StringEncoding, error: nil) | |
{ | |
let TESTCASE_SIZE = 50 | |
let onlyTestCase = false | |
var cnt = 0 | |
var failedIDs = [String]() | |
let start = NSDate.timeIntervalSinceReferenceDate() // 開始時間を記録 | |
data.enumerateLines{ line, stop in | |
cnt++; | |
if onlyTestCase { | |
if cnt > TESTCASE_SIZE { return } // テスト用データのみを実行 | |
} else { | |
if cnt <= TESTCASE_SIZE { return } // テスト用データを除外 | |
} | |
let data = SymmetryAxisData(raw: line) | |
let pass = data.checkData() | |
if !pass { failedIDs.append(data.id) } | |
} | |
println(join(",", failedIDs)) | |
println(NSDate.timeIntervalSinceReferenceDate() - start) // 経過時間を出力 | |
} | |
// | |
// search_symmetry_axis.swift | |
// | |
let indexLabels = [ | |
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", | |
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" | |
] | |
// 始点を終点を持つ直線を表すクラス | |
class Line:Equatable { | |
let a:Int | |
let b:Int | |
init(a:Int, b:Int) { | |
self.a = a | |
self.b = b | |
} | |
} | |
// 円周内の弦を表すクラス | |
class Chord:Line { | |
let resolution:Int // 円周内の点の数、何等分されているか | |
init(a:Int, b:Int, resolution:Int) { | |
self.resolution = resolution | |
super.init(a: a, b: b) | |
} | |
// 与えられた角度を軸として、自身の対称となる弦を返す | |
func reflect(angle:Double) -> Chord { | |
let doubleA = Double(a) | |
let doubleB = Double(b) | |
let reflectA = reflectPoint(angle, point: doubleA) | |
let reflectB = reflectPoint(angle, point: doubleB) | |
return Chord(a: Int(reflectA), b: Int(reflectB), resolution: resolution) | |
} | |
// 与えられた角度を軸として、与えられた点の対称となる点を返す | |
private func reflectPoint(angle:Double, point:Double) -> Double { | |
let doubleReso = Double(resolution) | |
return angle > point ? | |
(angle + (angle - point)) % doubleReso: | |
(angle + doubleReso - (point - angle)) % doubleReso | |
} | |
} | |
// 同じ始点と終点を持つ線を等しいものと認識する | |
func ==(l:Line, r:Line) -> Bool { | |
return l.a == r.a && l.b == r.b || | |
l.a == r.b && l.b == r.a | |
} | |
// id、線の数、図形が対称形となる軸の数、線の配列を持つクラス | |
class SymmetryAxisData { | |
let id:String | |
let linesCount:Int | |
let axisCount:Int | |
var lines = [Chord]() | |
init(raw:String) { | |
let splitted = split(raw){ $0 == "\t" } | |
id = splitted[0] | |
linesCount = splitted[1].toInt()! | |
axisCount = splitted[3].toInt()! | |
lines = split(splitted[2]){ $0 == "," }.map{ (labels:String) -> Chord in | |
var args = [Int]() | |
for c in labels { | |
args.append(find(indexLabels, String(c))!) // 点を表すアルファベットを0から始まる整数に変換する | |
} | |
return Chord(a: args[0], b: args[1], resolution: self.linesCount) | |
} | |
} | |
func checkData() -> Bool { | |
var axisCount = 0 | |
// ある点、もしくは隣り合う点と点を結ぶ円弧の中心点、 | |
// から円の中心を通って反対側までを結ぶ線を軸として、 | |
// 図形が対称形となるかどうかを確認する。 | |
per_angle: for i in 0..<self.linesCount { | |
let axisAngle = 0.5 * Double(i) | |
var matcher = lines | |
for line in lines { | |
let reflectedLine = line.reflect(axisAngle) | |
if let idx = find(matcher, reflectedLine) { | |
matcher.removeAtIndex(idx) | |
} else { | |
continue per_angle | |
} | |
} | |
axisCount++ | |
} | |
return axisCount == self.axisCount | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment