wigging (Gavin Wiggins) August 23, 2024, 7:18pm 21 This does not work. I used the following functions:
func cumulativeProdTwo(_ array: [Int]) -> [Int] { array.reduce(into: [Int]()) { partialResult, x in if let last = partialResult.last { partialResult.append(last * x + x - 1) } else { partialResult.append(x) } } } func descriptionTwo<T>(for array: [T], with shape: [Int]) -> String { if shape.count == 1 { var descr = "( " descr += array.map { "\($0)" }.joined(separator: " ") descr += " )" return descr } let chunkSize = shape.last ?? 1 let chunks = stride(from: 0, to: numbers.count, by: chunkSize).map { Array(numbers[$0..<min($0 + chunkSize, numbers.count)]) } let width = array.map { "\($0)".count }.max() ?? 1 let lines = chunks.map { row in row.map { element in (String(repeating: " ", count: width) + element.description).suffix(width) }.joined(separator: " ") } var r = shape r.removeLast() r.reverse() let rows = cumulativeProdTwo(r) var n = 0 let last = rows.last! var descr = "" func add(line: String) { for row in rows.reversed() { switch n % (row + 1) { case 0: descr += "⎛ " case row - 1: descr += "⎝ " case row: descr += " " default: descr += "⎜ " } } descr += line for row in rows { switch n % (row + 1) { case 0: descr += " ⎞" case row - 1: descr += " ⎠" case row: descr += " " default: descr += " ⎟" } } descr += "\n" n += 1 } for line in lines { if n % (last + 1) == last { add(line: String(repeating: " ", count: (width + 2) * chunkSize - 2)) } add(line: line) } return descr }
And I get the following result:
let shape = [2, 3, 2, 4] let numbers = Array(1...shape.reduce(1, *)) let d2 = descriptionTwo(for: numbers, with: shape) print(d2)
⎛ ⎛ ⎛ 1 2 3 4 ⎞ ⎞ ⎞ ⎜ ⎜ ⎝ 5 6 7 8 ⎠ ⎟ ⎟ ⎜ ⎜ 9 10 11 12 ⎟ ⎟ ⎜ ⎜ ⎛ 13 14 15 16 ⎞ ⎟ ⎟ ⎜ ⎜ ⎝ 17 18 19 20 ⎠ ⎟ ⎟ ⎜ ⎜ 21 22 23 24 ⎟ ⎟ ⎜ ⎜ ⎛ 25 26 27 28 ⎞ ⎟ ⎟ ⎜ ⎝ ⎝ 29 30 31 32 ⎠ ⎠ ⎟ ⎜ 33 34 35 36 ⎟ ⎜ ⎛ ⎛ 37 38 39 40 ⎞ ⎞ ⎟ ⎜ ⎜ ⎝ 41 42 43 44 ⎠ ⎟ ⎟ ⎜ ⎜ 45 46 47 48 ⎟ ⎟
xAlien95 (Stefano De Carolis) August 23, 2024, 11:04pm 22
wigging:
let last = rows.last!
Replace rows.last!
with rows.first!
.
ibex10 August 24, 2024, 12:13am 23 Yes
Use a WebView or get a browser to load it from an html file.
Details <!doctype html> <html> <header> <script id='MathJax-script' async src='https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'></script> </header> <body> <math xmlns='http://www.w3.org/1998/Math/MathML' display='inline'> <mrow> <mi mathsize='2.5em' mathcolor='#00AAFF'>x</mi> <mo mathsize='2.5em' mathcolor='#00AAFF'>=</mo> <mi mathsize='2.5em' mathcolor='#00AAFF'>x</mi> </mrow> </math> </body> </html>
No, but I would use a method similar to yours.
wigging (Gavin Wiggins) August 24, 2024, 12:45pm 24 Can you explain your changes to this function? It looks like the addition of x - 1
accounts for the extra blank lines in the printed array.
func cumulativeProd(_ array: [Int]) -> [Int] { array.reduce(into: [Int]()) { partialResult, x in if let last = partialResult.last { partialResult.append(last * x + x - 1) } else { partialResult.append(x) } } }
But this is no longer a cumulative product such as [a, b, c] -> [a, b * a, c * b]
it's more like [a, b*a + (b - 1), c*b + (c - 1)]
so maybe the function should be called something like calculateLastRows()
.
xAlien95 (Stefano De Carolis) August 24, 2024, 12:54pm 25 Yes, that's its purpose. You can call it calculateHeights
if you prefer. 2, 8 and 17 are the respective heights of the submatrices placed on top.
wigging (Gavin Wiggins) August 24, 2024, 1:31pm 26 Ok, this is what I have for the two functions:
func getLastRows(_ array: [Int]) -> [Int] { array.reduce(into: [Int]()) { partialResult, x in if let last = partialResult.last { partialResult.append(last * x + x - 1) } else { partialResult.append(x) } } } func descriptionTwo<T>(for array: [T], with shape: [Int]) -> String { if shape.count == 1 || shape.count == 2 && shape[0] == 1{ var descr = "( " descr += array.map { "\($0)" }.joined(separator: " ") descr += " )" return descr } let chunkSize = shape.last ?? 1 let chunks = stride(from: 0, to: numbers.count, by: chunkSize).map { Array(numbers[$0..<min($0 + chunkSize, numbers.count)]) } let width = array.map { "\($0)".count }.max() ?? 1 let lines = chunks.map { row in row.map { element in (String(repeating: " ", count: width) + element.description).suffix(width) }.joined(separator: " ") } var r = shape r.removeLast() r.reverse() let rows = getLastRows(r) // is [2, 8, 17] var n = 0 let last = rows.first ?? 1 var descr = "" func add(line: String) { for row in rows.reversed() { switch n % (row + 1) { case 0: descr += "⎛ " case row - 1: descr += "⎝ " case row: descr += " " default: descr += "⎜ " } } descr += line for row in rows { switch n % (row + 1) { case 0: descr += " ⎞" case row - 1: descr += " ⎠" case row: descr += " " default: descr += " ⎟" } } if n != rows.last! - 1 { descr += "\n" } n += 1 } for line in lines { if n % (last + 1) == last { add(line: String(repeating: " ", count: (width + 2) * chunkSize - 2)) } add(line: line) } return descr }
Which gives the following result:
let shape = [2, 3, 2, 4] let numbers = Array(1...shape.reduce(1, *)).map { Float($0) } let d2 = descriptionTwo(for: numbers, with: shape) print(d2)
⎛ ⎛ ⎛ 1.0 2.0 3.0 4.0 ⎞ ⎞ ⎞ ⎜ ⎜ ⎝ 5.0 6.0 7.0 8.0 ⎠ ⎟ ⎟ ⎜ ⎜ ⎟ ⎟ ⎜ ⎜ ⎛ 9.0 10.0 11.0 12.0 ⎞ ⎟ ⎟ ⎜ ⎜ ⎝ 13.0 14.0 15.0 16.0 ⎠ ⎟ ⎟ ⎜ ⎜ ⎟ ⎟ ⎜ ⎜ ⎛ 17.0 18.0 19.0 20.0 ⎞ ⎟ ⎟ ⎜ ⎝ ⎝ 21.0 22.0 23.0 24.0 ⎠ ⎠ ⎟ ⎜ ⎟ ⎜ ⎛ ⎛ 25.0 26.0 27.0 28.0 ⎞ ⎞ ⎟ ⎜ ⎜ ⎝ 29.0 30.0 31.0 32.0 ⎠ ⎟ ⎟ ⎜ ⎜ ⎟ ⎟ ⎜ ⎜ ⎛ 33.0 34.0 35.0 36.0 ⎞ ⎟ ⎟ ⎜ ⎜ ⎝ 37.0 38.0 39.0 40.0 ⎠ ⎟ ⎟ ⎜ ⎜ ⎟ ⎟ ⎜ ⎜ ⎛ 41.0 42.0 43.0 44.0 ⎞ ⎟ ⎟ ⎝ ⎝ ⎝ 45.0 46.0 47.0 48.0 ⎠ ⎠ ⎠
This works great except for some edge cases like:
let shape = [2, 3, 1, 4] let numbers = Array(1...shape.reduce(1, *)).map { Float($0) } let d2 = descriptionTwo(for: numbers, with: shape) print(d2)
⎛ ⎛ ⎛ 1.0 2.0 3.0 4.0 ⎞ ⎞ ⎞ ⎜ ⎜ ⎟ ⎟ ⎜ ⎜ ⎛ 5.0 6.0 7.0 8.0 ⎞ ⎟ ⎟ ⎜ ⎜ ⎟ ⎟ ⎜ ⎝ ⎛ 9.0 10.0 11.0 12.0 ⎞ ⎠ ⎟ ⎜ ⎟ ⎜ ⎛ ⎛ 13.0 14.0 15.0 16.0 ⎞ ⎞ ⎟ ⎜ ⎜ ⎟ ⎟ ⎜ ⎜ ⎛ 17.0 18.0 19.0 20.0 ⎞ ⎟ ⎟ ⎜ ⎜ ⎟ ⎟ ⎝ ⎝ ⎛ 21.0 22.0 23.0 24.0 ⎞ ⎠ ⎠
wigging (Gavin Wiggins) August 25, 2024, 4:22am 27 This handles the case where the base matrix is just one row:
func descriptionTwo<T>(for array: [T], with shape: [Int]) -> String { if shape.count == 1 || shape.count == 2 && shape[0] == 1 { var descr = "( " descr += array.map { "\($0)" }.joined(separator: " ") descr += " )" return descr } let chunkSize = shape.last ?? 1 let chunks = stride(from: 0, to: array.count, by: chunkSize).map { Array(array[$0..<min($0 + chunkSize, array.count)]) } let width = array.map { "\($0)".count }.max() ?? 1 let lines = chunks.map { row in row.map { element in (String(repeating: " ", count: width) + "\(element)").suffix(width) }.joined(separator: " ") } var r = shape r.removeLast() r.reverse() let rows = getLastRows(r) // is [2, 8, 17] var n = 0 let last = rows.first ?? 1 var descr = "" func add(line: String) { for row in rows.reversed() { switch n % (row + 1) { case 0: if row == 1 { descr += "( " } else { descr += "⎛ " } case row - 1: descr += "⎝ " case row: descr += " " default: descr += "⎜ " } } descr += line for row in rows { switch n % (row + 1) { case 0: if row == 1 { descr += " )" } else { descr += " ⎞" } case row - 1: descr += " ⎠" case row: descr += " " default: descr += " ⎟" } } if n != rows.last! - 1 { descr += "\n" } n += 1 } for line in lines { if n % (last + 1) == last { add(line: String(repeating: " ", count: (width + 2) * chunkSize - 2)) } add(line: line) } return descr }