import Foundation
class node {
var number:String
var inTime:String
var totalTime:Int? = nil
var next:node? = nil
var nowIn = false
init (_ number:String, _ inTime:String) {
self.number = number
self.inTime = inTime
self.totalTime = nil
self.next = nil
self.nowIn = true
}
}
var head:node? = nil
func addNode(_ newList:node?) {
var temp = head
if head == nil {
head = newList
}
while (temp?.next != nil) {
temp = temp?.next
}
temp?.next = newList
}
func findAdd(_ number:String, _ inTime:String) {
var temp = head
while (temp != nil) {
if number == temp?.number {
temp?.inTime = inTime
temp?.nowIn = true
}
temp = temp?.next
}
}
func check_number(_ number:String) -> Bool {
var temp = head
while (temp != nil) {
if number == temp?.number {
return false
}
temp = temp?.next
}
return true
}
func makeMinute(_ inTime:String) -> Int {
let sp = inTime.split(separator:":")
return Int(String(sp[0]))! * 60 + Int(String(sp[1]))!
}
func makeTotal (_ number:String, _ outTime:String) {
var temp = head
while (temp != nil) {
if (number == temp?.number) {
temp?.nowIn = false
if temp?.totalTime == nil {
temp?.totalTime = makeMinute(outTime) - makeMinute(temp!.inTime)
}
else {
temp?.totalTime! += makeMinute(outTime) - makeMinute(temp!.inTime)
}
}
temp = temp?.next
}
}
func nodeSort() -> [Int] {
var temp = head
var dict:[String:Int] = [:]
while temp != nil {
dict[temp!.number] = temp!.totalTime
temp = temp?.next
}
return dict.sorted { $0.0 < $1.0 }.map { $0.value }
}
func make_result(_ fees:[Int], _ totalTime:[Int]) -> [Int] {
var result:[Int] = []
for val in totalTime {
if val <= fees[0] {
result.append(fees[1])
continue
}
else {
var temp = val - fees[0]
temp = temp % fees[2] > 0 ? temp / fees[2] + 1 : temp/fees[2]
result.append(fees[1] + (temp * fees[3]))
}
}
return result
}
func solution(_ fees:[Int], _ records:[String]) -> [Int] {
for st in records {
let sp = st.split(separator: " ")
if sp[2] == "IN" {
if head == nil || check_number(String(sp[1])) {
let lst = node(String(sp[1]), String(sp[0]))
addNode(lst)
}
else {
findAdd(String(sp[1]), String(sp[0]))
}
}
else if sp[2] == "OUT" {
makeTotal(String(sp[1]), String(sp[0]))
}
}
var temp = head
while (temp != nil) {
if temp!.nowIn == true {
makeTotal(temp!.number, "23:59")
}
temp = temp?.next
}
return make_result(fees, nodeSort())
}
문제 링크 - 문제가 긴 편이라 링크로 대체
풀이 자체는 어렵지 않았다.
swift로 연결리스트를 구현하는건 처음이었다.
옵셔널 문법이 어려웠고, 문자열 처리는 여전히 귀찮았다.
주차장에 없는 차량의 출차 / 주차장 안에 있는 차량과 같은 번호의 차량은 진입하지 않는다. 등의 잘못된 입력은 주어지지 않아 예외처리는 생각하지 않아도 되었다.
class node {
var number:String
var inTime:String
var totalTime:Int? = nil
var next:node? = nil
var nowIn = false
init (_ number:String, _ inTime:String) {
self.number = number
self.inTime = inTime
self.totalTime = nil
self.next = nil
self.nowIn = true
}
}
한 차량에 대한 하루동안의 총 이용시간을 계산해야했기에 연결리스트가 먼저 떠올랐다. (여러번 입차했을 경우 등)
func solution(_ fees:[Int], _ records:[String]) -> [Int] {
for st in records {
let sp = st.split(separator: " ")
if sp[2] == "IN" {
if head == nil || check_number(String(sp[1])) {
let lst = node(String(sp[1]), String(sp[0]))
addNode(lst)
}
else {
findAdd(String(sp[1]), String(sp[0]))
}
}
else if sp[2] == "OUT" {
makeTotal(String(sp[1]), String(sp[0]))
}
}
var temp = head
while (temp != nil) {
if temp!.nowIn == true {
makeTotal(temp!.number, "23:59")
}
temp = temp?.next
}
return make_result(fees, nodeSort())
}
일단 반복문을 돌리며 split을 통해 공백기준으로 문자를 분리했다.
sp선언부를 for문으로 올려도 됐을듯?
for sp in records.split(separator:" ") //느낌으로
이후 In,Out에 따라 분기를 정했다.
In이면서 헤드노드가 비어있거나 중복되는 차량번호(check_number)가 없었다면 새 노드를 생성해주었다.
아니라면 기존 노드를 탐색하여 같은 차량번호에 값을 넣어주었다.
Out일 경우 총 이용시간을 계산하여 node의 totalTime에 넣어주었다.
while을 통해 입차만 하고 출차를 하지 않은 경우(nowIn == true) 23:59분에 출차한것으로 처리해주었다.
이 데이터를 차량번호 순으로 정렬하여 답만 내주면 되었다.
func nodeSort() -> [Int] {
var temp = head
var dict:[String:Int] = [:]
while temp != nil {
dict[temp!.number] = temp!.totalTime
temp = temp?.next
}
return dict.sorted { $0.0 < $1.0 }.map { $0.value }
}
어떤식으로 처리할지 고민하다 C++의 map같은 자료형를 사용하고 싶어서 유사한 딕셔너리 타입을 사용했다.
차량 번호를 key로, 총 이용시간을 value로 지정했다.
sorted를 사용하는 부분에서 문법적으로 좀 어려웠다. $0.0에서 .0은 key를 뜻한다. key끼리 비교해서 sort 해줘라 정도로 해석하면 되겠다.
차량번호의 역할은 sort에서 끝이다. map을 활용하여 value만 정리해서 Int형 배열로 리턴해주었다.
func make_result(_ fees:[Int], _ totalTime:[Int]) -> [Int] {
var result:[Int] = []
for val in totalTime {
if val <= fees[0] {
result.append(fees[1])
continue
}
else {
var temp = val - fees[0]
temp = temp % fees[2] > 0 ? temp / fees[2] + 1 : temp/fees[2]
result.append(fees[1] + (temp * fees[3]))
}
}
return result
}
마지막 계산부분은 문제에서 모두 제시해주었다.
기본요금보다 적게 이용했다면 기본요금만, 아니라면 기본요금 + 단위에 따른 추가금을 올림처리하여 더해주기.
옵셔널 언래핑과정에서 ?와 !를 많이 혼용해서 사용했는데 이 부분은 더 찾아봐야할듯
옵셔널 언래핑
!은 강제 언래핑으로 nil이 아님을 확신할때만 사용하는 문법이고, 실무에선 쓰지 않는것이 원칙이라고...