Railway circuit: Difference between revisions

Content added Content deleted
m (→‎{{header|Phix}}: 50% faster)
(Add Swift)
Line 1,185: Line 1,185:
(0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 1)
(0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 1)
(0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1)</pre>
(0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1)</pre>


=={{header|Swift}}==

{{trans|Kotlin}}

<lang swift>enum Track: Int, Hashable {
case left = -1, straight, right
}

extension Track: Comparable {
static func < (lhs: Track, rhs: Track) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}

func < (lhs: [Track], rhs: [Track]) -> Bool {
for (l, r) in zip(lhs, rhs) where l != r {
return l < r
}

return false
}

func normalize(_ tracks: [Track]) -> [Track] {
let count = tracks.count
var workingTracks = tracks
var norm = tracks

for _ in 0..<count {
if workingTracks < norm {
norm = workingTracks
}

let temp = workingTracks[0]

for j in 1..<count {
workingTracks[j - 1] = workingTracks[j]
}

workingTracks[count - 1] = temp
}

return norm
}

func fullCircleStraight(tracks: [Track], nStraight: Int) -> Bool {
guard nStraight != 0 else {
return true
}

guard tracks.filter({ $0 == .straight }).count == nStraight else {
return false
}

var straight = [Int](repeating: 0, count: 12)
var i = 0
var idx = 0

while i < tracks.count && idx >= 0 {
if tracks[i] == .straight {
straight[idx % 12] += 1
}

idx += tracks[i].rawValue
i += 1
}

return !((0...5).contains(where: { straight[$0] != straight[$0 + 6] }) &&
(0...7).contains(where: { straight[$0] != straight[$0 + 4] })
)
}

func fullCircleRight(tracks: [Track]) -> Bool {
guard tracks.map({ $0.rawValue * 30 }).reduce(0, +) % 360 == 0 else {
return false
}

var rightTurns = [Int](repeating: 0, count: 12)
var i = 0
var idx = 0

while i < tracks.count && idx >= 0 {
if tracks[i] == .right {
rightTurns[idx % 12] += 1
}

idx += tracks[i].rawValue
i += 1
}

return !((0...5).contains(where: { rightTurns[$0] != rightTurns[$0 + 6] }) &&
(0...7).contains(where: { rightTurns[$0] != rightTurns[$0 + 4] })
)
}

func circuits(nCurved: Int, nStraight: Int) {
var solutions = Set<[Track]>()

for tracks in getPermutationsGen(nCurved: nCurved, nStraight: nStraight)
where fullCircleStraight(tracks: tracks, nStraight: nStraight) && fullCircleRight(tracks: tracks) {
solutions.insert(normalize(tracks))
}

report(solutions: solutions, nCurved: nCurved, nStraight: nStraight)
}

func getPermutationsGen(nCurved: Int, nStraight: Int) -> PermutationsGen {
precondition((nCurved + nStraight - 12) % 4 == 0, "input must be 12 + k * 4")

let trackTypes: [Track]

if nStraight == 0 {
trackTypes = [.right, .left]
} else if nCurved == 12 {
trackTypes = [.right, .straight]
} else {
trackTypes = [.right, .left, .straight]
}

return PermutationsGen(numPositions: nCurved + nStraight, choices: trackTypes)
}

func report(solutions: Set<[Track]>, nCurved: Int, nStraight: Int) {
print("\(solutions.count) solutions for C\(nCurved),\(nStraight)")

if nCurved <= 20 {
for tracks in solutions {
for track in tracks {
print(track.rawValue, terminator: " ")
}

print()
}
}
}

struct PermutationsGen: Sequence, IteratorProtocol {
private let choices: [Track]
private var indices: [Int]
private var sequence: [Track]
private var carry = 0

init(numPositions: Int, choices: [Track]) {
self.choices = choices
self.indices = .init(repeating: 0, count: numPositions)
self.sequence = .init(repeating: choices.first!, count: numPositions)
}

mutating func next() -> [Track]? {
guard carry != 1 else {
return nil
}

carry = 1
var i = 1

while i < indices.count && carry > 0 {
indices[i] += carry
carry = 0

if indices[i] == choices.count {
carry = 1
indices[i] = 0
}

i += 1
}

for j in 0..<indices.count {
sequence[j] = choices[indices[j]]
}

return sequence
}
}

for n in stride(from: 12, through: 32, by: 4) {
circuits(nCurved: n, nStraight: 0)
}

circuits(nCurved: 12, nStraight: 4)</lang>

{{out}}

<pre>1 solutions for C12,0
1 1 1 1 1 1 1 1 1 1 1 1

1 solutions for C16,0
-1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1

6 solutions for C20,0
-1 1 -1 1 1 1 1 1 1 1 -1 1 -1 1 1 1 1 1 1 1
-1 1 1 -1 1 1 1 1 1 1 -1 1 1 -1 1 1 1 1 1 1
-1 -1 1 1 1 1 1 1 1 1 -1 -1 1 1 1 1 1 1 1 1
-1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 -1 1 1 1 1 1
-1 -1 1 1 1 1 1 1 1 -1 1 1 -1 1 1 1 1 1 1 1
-1 1 1 1 1 -1 1 1 1 1 -1 1 1 1 1 -1 1 1 1 1

40 solutions for C24,0

243 solutions for C28,0

2134 solutions for C32,0

4 solutions for C12,4
0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1
0 1 0 1 1 1 1 1 0 1 0 1 1 1 1 1
0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1
0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 1</pre>


=={{header|zkl}}==
=={{header|zkl}}==