Looping through an array of arrays with Swift
…and finding the greatest product horizontally, vertically or diagonally.
Finding out the largest product was fairly simple using Swift. The global enumerate function for looping through the arrays was an especially nice feature. It returns a tuple with the value and the index, see more in Apple’s Book “The Swift Programming Language” page 102. You can read the book from Apple’s iBooks for free.
Since this is my first Swift post I will post event the copyright header to show you what Xcode generates.
//
// main.swift
//
// Created by T. Urtti on 11.6.2014.
// Copyright (c) 2014 T. Urtti. All rights reserved.
//
After this I create the array of int arrays. Now notice how I don’t declare anything explicitly to be an array nor do I explicitly define anything to be integer. This code fully utilizes the type inference that is a part of Swift. The compiler understands automatically that the gridOfGrids is an array and that the array elements are int arrays.
let gridOfGrids = [
[08, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91, 08],
[49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 04, 56, 62, 00],
[81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 03, 49, 13, 36, 65],
[52, 70, 95, 23, 04, 60, 11, 42, 69, 24, 68, 56, 01, 32, 56, 71, 37, 02, 36, 91],
[22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
[24, 47, 32, 60, 99, 03, 45, 02, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50],
[32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70],
[67, 26, 20, 68, 02, 62, 12, 20, 95, 63, 94, 39, 63, 08, 40, 91, 66, 49, 94, 21],
[24, 55, 58, 05, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72],
[21, 36, 23, 09, 75, 00, 76, 44, 20, 45, 35, 14, 00, 61, 33, 97, 34, 31, 33, 95],
[78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 03, 80, 04, 62, 16, 14, 09, 53, 56, 92],
[16, 39, 05, 42, 96, 35, 31, 47, 55, 58, 88, 24, 00, 17, 54, 24, 36, 29, 85, 57],
[86, 56, 00, 48, 35, 71, 89, 07, 05, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],
[19, 80, 81, 68, 05, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 04, 89, 55, 40],
[04, 52, 08, 83, 97, 35, 99, 16, 07, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],
[88, 36, 68, 87, 57, 62, 20, 72, 03, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69],
[04, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 08, 46, 29, 32, 40, 62, 76, 36],
[20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 04, 36, 16],
[20, 73, 35, 29, 78, 31, 90, 01, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 05, 54],
[01, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 01, 89, 19, 67, 48]]
You may have noticed I declared it using the keyword ‘let’ instead of ‘var’. This is to make the array constant, un-modifiable.
Now I will calculate the max index for a diagonal product calculation and also declare that a constant. And define the variable that gets updated with the largest product.
let maxIndex = gridOfGrids[0].count - 4
var largestProduct = 0
Now this is more exciting. Swift gives you a very handy enumerate function for looping through an array. The enumerate function returns a tuple including both index and the actual value. Yes, you can use tuples in Swift.
I won’t talk more in detail about the actual product checks in the loops as they are quite generic to any programming language.
for (rowIndex, row) in enumerate(gridOfGrids)
{
for (columnIndex, number) in enumerate(row)
{
// Horizontal check
if (columnIndex >= 3)
{
var product = row[columnIndex-3] *
row[columnIndex-2] *
row[columnIndex-1] *
number
if largestProduct < product
{
largestProduct = product
}
}
// Vertical check
if (rowIndex >= 3)
{
var product = (gridOfGrids[rowIndex-3])[columnIndex] *
(gridOfGrids[rowIndex-2])[columnIndex] *
(gridOfGrids[rowIndex-1])[columnIndex] *
number
if largestProduct < product
{
largestProduct = product
}
}
// Diagonal up-left -> bottom-right
if (rowIndex >= 3 && columnIndex >= 3)
{
var product = (gridOfGrids[rowIndex-3])[columnIndex-3] *
(gridOfGrids[rowIndex-2])[columnIndex-2] *
(gridOfGrids[rowIndex-1])[columnIndex-1] *
number
if largestProduct < product
{
largestProduct = product
}
}
// Diagonal bottom-left -> up-right
if (rowIndex >= 3 && columnIndex <= maxIndex)
{
var product = (gridOfGrids[rowIndex-1])[columnIndex+1] *
(gridOfGrids[rowIndex-2])[columnIndex+2] *
(gridOfGrids[rowIndex-3])[columnIndex+3] *
number
if largestProduct < product
{
largestProduct = product
}
}
}
}
And finally just a simple printout to find out what was actually calculated in all of this. Println apparently is somehow a context-aware function that prints to the appropriate output. In Xcode it printed to the debug output.
println("Largest Product: " + String(largestProduct))
Great, that wasn’t too difficult! Overall the syntax feels more or less at home for somebody coming mainly from a C++ background.