DEV Community

Discussion on: Daily Challenge #77 - Bird Mountain

Collapse
 
earlware profile image
EarlWare

Swift Solution:

import Foundation


//                 0    1    2    3    4    5    6    7    8    9   10   11   12   13
let mountain = [ ["^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " ", " ", " ", " "],   // 0
                 [" ", "^", "^", "^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " "],   // 1
                 [" ", " ", "^", "^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " "],   // 2
                 [" ", " ", "^", "^", "^", "^", "^", "^", " ", " ", " ", " ", " ", " "],   // 3
                 [" ", " ", "^", "^", "^", "^", "^", "^", "^", "^", "^", "^", "^", "^"],   // 4
                 [" ", " ", "^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " ", " "],   // 5
                 [" ", " ", "^", "^", "^", "^", "^", " ", " ", " ", " ", " ", " ", " "] ]  // 6

//  simple check to see if its the selected tile for mountains.
func isMountainTile(tile:String) -> Bool {
    return tile == "^"
}

//  simple helper to check if any mountain tiles remain in the tileset
func hasMountains(mount:[[String]]) -> Bool {
    for rows in mount {
        for col in rows {
            if isMountainTile(tile:col) {
                return true
            }
        }
    }
    return false
}

//  simple helper to print out tileset neatly
func printMountain(mount:[[String]]) {
    for row in mount {
        print(row)
    }
}

/*
isValid

@param mount  2d array
@param row    the row of the slot we are looking at
@param col    the column of the slot we are looing at

@return returns true if the row & col are within the valid range of the given 2d array.
*/
func isValid(mount:[[String]], row:Int, col:Int) -> Bool {
    return ((row >= 0 || row < mount.count) || (col >= 0 || col < mount[row].count))
}

/*
 edgeCase

 @param mount  2d array of single character strings of either mountain tiles '^' or something else
 @param row    the row of the slot we are looking at
 @param col    the column of the slot we are looing at

 @return returns true if the row/col is accessible from an edge(left/right/up/down)
 */
func isEdgeCase(mount:[[String]], row:Int, col:Int) -> Bool {
    if !isValid(mount: mount, row: row, col: col) {
        return false
    } else {
        if (row == 0 || row == (mount.count-1)) || (col == 0 || col == (mount[row].count-1)) {
            return true     // we are definitely on an edge!
        } else if (!isMountainTile(tile:mount[row][col+1]) ||
                   !isMountainTile(tile:mount[row][col-1])) {
            return true // non mountain is either in front or behind us
        } else if (!isMountainTile(tile:mount[row+1][col]) ||
                   !isMountainTile(tile:mount[row-1][col])) {
           return true // non mountain is either above or below us
        }
    }
    return false
}

/*
 Challenge function BirdMountain

 @param 2d array of single character strings, either white space ' '  or mountain  '^'

 @return returns an Int of the calculated 'Height' of the mountain passed in.
*/
func birdMountain(mount:[[String]]) -> Int {
    var mountTiles = mount
    var cachedTiles = mountTiles
    var passNum = 0

    repeat {
        cachedTiles = mountTiles
        passNum += 1
        for row in 0..<mount.count {
            for col in 0..<mount[row].count {
                //  check every tile to see if its a mountain tile, and if so compare to the cached version to see if its an edge case.
                if (isMountainTile(tile:mountTiles[row][col]) &&
                    isEdgeCase(mount: cachedTiles, row: row, col: col)) {

                    mountTiles[row][col] = String(passNum)
                }
            }
        }
        print("Pass   #", passNum)
        printMountain(mount: mountTiles)
    } while hasMountains(mount: mountTiles)

    return passNum
}


print("Initial Mountain:  ")
printMountain(mount: mountain)
print("\n")


print("Height of the mountain is:   ", birdMountain(mount: mountain), "\n\n")

Output:

Initial Mountain:  
["^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " ", " ", " ", " "]
[" ", "^", "^", "^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " "]
[" ", " ", "^", "^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " "]
[" ", " ", "^", "^", "^", "^", "^", "^", " ", " ", " ", " ", " ", " "]
[" ", " ", "^", "^", "^", "^", "^", "^", "^", "^", "^", "^", "^", "^"]
[" ", " ", "^", "^", "^", "^", "^", "^", "^", " ", " ", " ", " ", " "]
[" ", " ", "^", "^", "^", "^", "^", " ", " ", " ", " ", " ", " ", " "]


Pass   # 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", " ", " ", " ", " ", " ", " ", " "]
Pass   # 2
["1", "1", "1", "1", "1", "1", "1", " ", " ", " ", " ", " ", " ", " "]
[" ", "1", "2", "2", "2", "2", "2", "1", "1", "1", " ", " ", " ", " "]
[" ", " ", "1", "2", "^", "^", "^", "2", "1", "1", " ", " ", " ", " "]
[" ", " ", "1", "2", "^", "^", "2", "1", " ", " ", " ", " ", " ", " "]
[" ", " ", "1", "2", "^", "^", "^", "2", "1", "1", "1", "1", "1", "1"]
[" ", " ", "1", "2", "2", "2", "2", "1", "1", " ", " ", " ", " ", " "]
[" ", " ", "1", "1", "1", "1", "1", " ", " ", " ", " ", " ", " ", " "]
Pass   # 3
["1", "1", "1", "1", "1", "1", "1", " ", " ", " ", " ", " ", " ", " "]
[" ", "1", "2", "2", "2", "2", "2", "1", "1", "1", " ", " ", " ", " "]
[" ", " ", "1", "2", "3", "3", "3", "2", "1", "1", " ", " ", " ", " "]
[" ", " ", "1", "2", "3", "3", "2", "1", " ", " ", " ", " ", " ", " "]
[" ", " ", "1", "2", "3", "3", "3", "2", "1", "1", "1", "1", "1", "1"]
[" ", " ", "1", "2", "2", "2", "2", "1", "1", " ", " ", " ", " ", " "]
[" ", " ", "1", "1", "1", "1", "1", " ", " ", " ", " ", " ", " ", " "]
Height of the mountain is:    3 


Program ended with exit code: 0

Definitely feel like I'm going a little heavy on the looping, but I was having a hard time visualizing how I could map the increasing elevations without keeping a reference copy of the array to make sure I wasn't just blowing through everything on each pass.... Any suggestions for improvements would be appreciated!