Skip to content

Instantly share code, notes, and snippets.

@ZevEisenberg
Last active February 17, 2020 18:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZevEisenberg/52330bf5a28549db91bb29512b808f05 to your computer and use it in GitHub Desktop.
Save ZevEisenberg/52330bf5a28549db91bb29512b808f05 to your computer and use it in GitHub Desktop.
Find how long it takes for an async siteswap to loop
//
// main.swift
// Swapper
//
// Created by Zev Eisenberg on 12/4/17.
// Copyright © 2017 Zev Eisenberg. All rights reserved.
//
// Code ported from https://www.reddit.com/r/juggling/comments/7839h0/find_number_of_beats_to_loop_a_given_siteswap/douuezu/
// It finds how many beats you would have to juggle an async siteswap pattern before
// all the balls are back in their starting state.
func gcd(_ m: Int, _ n: Int) -> Int {
var a = 0
var b = max(m, n)
var r = min(m, n)
while r != 0 {
a = b
b = r
r = a % b
}
return b
}
assert(gcd(3, 6) == 3)
assert(gcd(15, 20) == 5)
assert(gcd(16, 20) == 4)
func lcm(_ m: Int, _ n: Int) -> Int {
return m / gcd(m, n) * n
}
assert(lcm(10, 8) == 40)
extension Array where Element: Numeric {
var sum: Element {
return reduce(into: 0, { $0 += $1 })
}
}
extension BinaryInteger {
var isOdd: Bool {
return self % 2 == 1
}
var doubledIfOdd: Self {
if isOdd {
return self * 2
}
return self
}
}
assert([1, 2, 3].sum == 6)
assert(1.doubledIfOdd == 2)
assert(4.doubledIfOdd == 4)
//let siteswap = [1, 2, 3, 4, 5, 6, 7]
//let siteswap = [5, 0, 1]
//let siteswap = [5, 1]
let siteswap = [9, 7, 5, 3, 1]
//let siteswap = [4, 4, 1]
//let siteswap = [7, 4, 4]
//let siteswap = [4, 2]
var tested = Array(repeating: false, count: siteswap.count)
var loops: [[Int]] = []
var loopNum = 0
// First, find the loops in the siteswap. Examples:
// - the loops in 1234567 are (124, 365, 7).
// - the loops in 51 are (51).
// - the loops in 42 are (4, 2).
for i in 0..<siteswap.count where !tested[i] && siteswap[i] != 0 {
var curTest = i
inner: while true {
if tested[curTest] {
loopNum += 1
break inner
}
else {
if loops.count <= loopNum {
loops.append([])
}
loops[loopNum].append(siteswap[curTest])
tested[curTest] = true
curTest = (curTest + siteswap[curTest]) % siteswap.count
}
}
}
print(loops)
let leastCommonMultiple = loops.map { loop in loop.sum.doubledIfOdd }.reduce(into: 1, { $0 = lcm($0, $1) })
print(leastCommonMultiple)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment