Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
CodeIQ 「中学入試から:対称軸の本数を数えよう」提出コード
//
// 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