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!.
ibex
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
}