Extracting values from a reversed linked list - swift

Question:
You have two numbers represented by a linked list, where each node contains a single digit. The digits are stored in reverse order, such that the 1 's digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list.
An Example:
Input: (7-> 1 -> 6) + (5 -> 9 -> 2).
That is: 617 + 295.
Output: 2 -> 1 -> 9.
That is: 912.
In order to begin with this question, I first created a class that would define what a linked list:
Step 1: Defining the linked list
class Node: CustomStringConvertible{
var value: Int
var next: Node?
var description: String{
if next != nil {
return "\(value) -> \(next!)"
}
else{
return "\(value) -> \(next)"
}
}
init(value: Int) {
self.value = value
}
}
Step: 2 - Generated the linked list, from user input of integer values
func generateList (num: Int) -> Node {
var stringNum = Array(String(num).characters)
let head = Node.init(value:Int(String(stringNum.first!))!)
var current = head
for i in 1..<stringNum.count{
let num = Int(String(stringNum[i]))
current.next = Node.init(value: num!)
current = current.next!
}
return head
}
let list = generateList(num: 716)
// The following prints out: 7 -> 1 -> 6 -> nil
Then I proceeded over to reverse the linked list using following function.
Step 3: Reverse the linked list
func reverseLinkedList (head: Node?) -> Node?{
var current = head
var prev: Node?
var next: Node?
while current != nil {
next = current?.next
current?.next = prev
prev = current
current = next
}
return prev
}
let reversedList = reverseLinkedList(head: list)
// The following prints out is: 6 -> 1 -> 7 -> nil
Step 4: The idea behind this step is to extract the values on each of the nodes, cast them as a string and then concatenate them to a string variable and then lastly cast the string value into an Int and then use that Int value and eventually add them.
func getValuesFrom (head: Node?) -> Int {
var string = ""
var current = head
while current != nil {
var stringVal = String(describing: current?.value)
string += stringVal
current = current?.next
}
return Int(string)!
}
Here is where I am having a problem:
When I plug in the following into this function like so:
getValuesFrom(head: reversedList)
I get the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
And I can't seem to figure out why I having a problem and would really appreciate any sort of insight.

There is no need to convert back and forth between String and the linked list, except to print it for results. This is done simply like this:
class Node {
var value: Int
var next: Node?
// init and generator can be the same method
init(value: Int) {
// store ones place and divide by 10
self.value = value % 10
var nextValue = value / 10
// set up for loop
var currentNode = self
while nextValue > 0 {
// create a new Node
// store ones place and divide by 10
let next = Node(value: nextValue % 10)
nextValue /= 10
// make the new Node the next Node
currentNode.next = next
// set up for next iteration
currentNode = next
}
}
}
// make the list printable
extension Node: CustomStringConvertible {
var description: String{
if let next = next {
return "\(value) -> \(next)"
}
else {
return "\(value) -> nil"
}
}
}
Now you can do:
print(Node(value: 671)) // prints "7 -> 1 -> 6 -> nil"
There is also no need to reverse the lists, given your question.
To sum the lists you can do just as you've said, convert to an Int, add them, then generate a new list:
extension Node {
func toValue() -> Int {
var place = 10
var current = self
// add each value and multiply by the place value
// first is 1, second 10, third 100, etc.
var result = current.value
while let next = current.next {
result += next.value * place
place *= 10
current = next
}
return result
}
}
Then all you need is to overload the addition operator...
func +(lhs: Node, rhs: Node) -> Node {
return Node(value: lhs.toValue() + rhs.toValue())
}
and test...
let first = Node(value: 617)
let second = Node(value: 295)
print(first)
print(second)
print(first + second)
Result:
7 -> 1 -> 6 -> nil
5 -> 9 -> 2 -> nil
2 -> 1 -> 9 -> nil

Related

Maximum Depth of N-ary Tree - swift

https://leetcode.com/problems/maximum-depth-of-n-ary-tree/
I've already solved this through other ways. I'm just trying to resolve it through this code. Trying to figure out what's incorrect for this. It currently returns incorrect results:
class Solution {
func maxDepth(_ root: Node?) -> Int {
guard let node = root else { return 0 }
return node.children.map(maxDepth).max() ?? 0 + 1
}
}
Helper class if you wanted to test this on Xcode:
class Node {
var value: Int
var children: [Node] = []
weak var parent: Node?
init(value: Int) {
self.value = value
}
func add(child: Node) {
children.append(child)
child.parent = self
}
}
Example:
let one = Node(value: 1)
let two = Node(value: 2)
let three = Node(value: 3)
one.add(child: two)
two.add(child: three)
print("res", maxDepth(one)) // returns: 2. Expected: 3
I'm always returning 2 actually. Not sure why...
Shout out to Martin for helping me figure this out.
Pro tip. For such leetcode style questions. The dumbest/simplest tests are the best.
The line below has 2 mistakes:
return node.children.map(maxDepth).max() ?? 1 + 1
The ?? is defaulting it to 0 + 1. Wrap the ?? in a parenthesis
The default should actually be 0. Not 1
So just do:
return (node.children.map(maxDepth).max() ?? 0) + 1
I made that mistake because I almost never have any arithmetic operations after the ?? 🤦‍♂️

bug in the remove function in my LinkedList in swift

I am trying to implement a generic linkedList API like in Java in swift.This has been done probably in hundreds of ways but my question is not on how to do it rather, on what is wrong with a part of my logic when removing an item whose index is zero. I know, there are alternate ways to achieve what I want and I did that but I need to understand the flaw in a particular logic. please have a look.
I have following functions for now.
var size : Int { get } //give the size of the list
func add(_ value: Item) //add items to the list
func removeAt(index: Int) // removes the item from the specified index
func print() //prints the list
My logic flaw is in the remove(index:) method only when I try to remove an item from the beginning of the list(index=0). My logic is to set the head's next node to be the head if there are more than 1 item in the list(list.size>0).
The following is the full implementation-
import Foundation
class Node<Item>{
var value: Item
var next: Node?
init(value: Item) {
self.value = value
self.next = nil
}
}
class LinkedList<Item> {
var head: Node<Item>?
public init(){
self.head = nil
}
public init(_ value: Item){
self.head = Node(value: value)
}
private func isEmpty()->Bool{
if head == nil{
return true
}
return false
}
var size : Int {
guard var current = head else{
return 0
}
var count = 1
while current.next != nil {
guard let next = current.next else {
return count
}
count = count + 1
current = next
}
return count
}
func add(_ value: Item){
let node = Node(value: value)
if isEmpty(){
head = node
return
}
guard let head = head else {
return
}
var currentNode = head
while currentNode.next != nil {
guard let nextNode = currentNode.next else {
break
}
currentNode = nextNode
}
currentNode.next = node
}
func removeAt(index: Int) {
if isEmpty() || index >= self.size{
return
}
guard var last = head, var secondLast = head else{
return
}
// when index is zero and either the list has only one item or it has multiple items
if index == 0{ //here is the bug
if let next = last.next{
last = next
}else{
head = nil
}
return
}
var count = 0
while count < index{
guard let next = last.next else{
return
}
secondLast = last
last = next
count = count + 1
}
secondLast.next = last.next
}
func print(){
guard var current = head else {
return
}
if current.next == nil{ //if list contains only head
Swift.print(current.value)
return
}
while current.next != nil{
Swift.print(current.value)
guard let next = current.next else {
return
}
current = next
}
Swift.print(current.value)
}
}
Testing the code like -
let list = LinkedList<Int>()
for i in 0...5{
list.add(i)
}
list.print()
let index = 0
list.removeAt(index: index)
print("After removing..")
list.print()
Output:
1
2
3
4
5
After removing..
1
2
3
4
5
Can anyone please points out my fault.
The head of the list becomes the next item, if there is one. If the next item is nil, then the head of the list is also nil, like so:
if index == 0 { //here is the bug
head = head?.next
return
}
This code:
if let next = last.next{
last = next
}else{
head = nil
}
In the first branch, you return without changing "head", so the head of the list remains unchanged.
suppose head is at address 100
and the second item in the list is at address 200
let list = LinkedList<Int>()
list's head -> 100
in remove at index 0 we set last to head, and secondLast also to head
last -> 100[ |next -> 200]
secondLast -> 100[ |next -> 200]
then we say
if let next = last.next { last = next } return
Now last points to 200:
last -> 200[ |next -> 300]
But list's head hasn't changed
list's head -> 100[ |next -> 200]
secondLast -> 100[ |next -> 200]
Last goes out of scope, when we return, no changes to the list structure (in the heap) have happened.
In the working branch (where index > 0):
while count < index{
guard let next = last.next else{
return
}
secondLast = last
last = next
count = count + 1
}
secondLast.next = last.next
we go over the loop manipulating secondLast and last, and at some point we then reach the line
secondLast.next = ...
So then we actually assign to the object, we mutate the object in the heap, it's next pointer, we go from something like:
secondLast -> 100[ |next -> 200]
secondLast -> 100[ |next -> 300]
So now the list itself has changed, in the heap, the object at address e.g. 100 has a next pointer that is pointing to some object, e.g. at address 300.
Firstly, I really appreciate the time and effort #Shadowrun put into. However, the explanation still lack the reason as of why the code works when I am iterating the list and removing in between the list.
The reason is List itself only holds one pointer, head which is referring to an address in memory. Sure the last node points to the same address but when I try to update update the head (index = 0) with the help of last, last is points to a different address which means it deviates from head as soon as it leaves the scope. While list has no clue that there was a change and list still holds the same pointer to address as of before.
Now when I am iterating from head(index>0), the last is same as head and with each iteration the last moves forward to the next node. I change the next pointer of any node at anytime, the next pointer gets updated for that node successfully. Here the starting node is same as head as last and head is pointing to the same address. So, for iteration over the list, it doesn't matter whether I start with head or last, the chain linking is same. Here head and last is same at the beginning. But for index = 0, as list's head, itself needs to be changed, making last pointing to a different node won't work because list knows head and the head is not updated.
So, the real reason is the list has no clue of how the node's are inter-related with one exception and that is the head.
It's not about assigning object or anything else. It's about list pointing to only one node and that is head.

Sorting arrays based on number of matches

I am trying to find the number of array item matches between multiple test arrays and one control array. After finding the number of matches, I want to append the test arrays to another array, sorted by number of matches between the control array and test array. For example, a test array with 3 matches would be at index 0, 2 matches at index 1, and so on.
let controlArray = ["milk", "honey"]
let test1 = ["honey", "water"]
let test2 = ["milk", "honey", "eggs"]
var sortedArrayBasedOnMatches = [[String]]()
/*I want to append test1 and test2 to sortedArrayBasedOnMatches based on how many items
test1 and test2 have in common with controlArray*/
/*in my example above, I would want sortedArrayBasedOnMatches to equal
[test2, test1] since test 2 has two matches and test 1 only has one*/
This can be done in a very functional and Swiftish way by writing a pipeline to process the input arrays:
let sortedArrayBasedOnMatches = [test1, test2] // initial unsorted array
.map { arr in (arr, arr.filter { controlArray.contains($0) }.count) } // making pairs of (array, numberOfMatches)
.sorted { $0.1 > $1.1 } // sorting by the number of matches
.map { $0.0 } // getting rid of the match count, if not needed
Update As #Carpsen90 pointed out, Switf 5 comes with support for count(where:) which reduces the amount of code needed in the first map() call. A solution that makes use of this could be written along the lines of
// Swift 5 already has this, let's add it for current versions too
#if !swift(>=5)
extension Sequence {
// taken from the SE proposal
// https://github.com/apple/swift-evolution/blob/master/proposals/0220-count-where.md#detailed-design
func count(where predicate: (Element) throws -> Bool) rethrows -> Int {
var count = 0
for element in self {
if try predicate(element) {
count += 1
}
}
return count
}
}
#endif
let sortedArrayBasedOnMatches = [test1, test2] // initial unsorted array
.map { (arr: $0, matchCount: $0.count(where: controlArray.contains)) } // making pairs of (array, numberOfMatches)
.sorted { $0.matchCount > $1.matchCount } // sorting by the number of matches
.map { $0.arr } // getting rid of the match count, if not needed
Another change in style from the original solution is to use labels for the tuple components, this makes the code a little bit clearer, but also a little bit more verbose.
One option is to convert each array to a Set and find the count of elements in the intersection with controlArray.
let controlArray = ["milk", "honey"]
let test1 = ["honey", "water"]
let test2 = ["milk", "honey", "eggs"]
var sortedArrayBasedOnMatches = [ test1, test2 ].sorted { (arr1, arr2) -> Bool in
return Set(arr1).intersection(controlArray).count > Set(arr2).intersection(controlArray).count
}
print(sortedArrayBasedOnMatches)
This will cover the case where elements are not unique in your control array(such as milk, milk, honey...) and with any number of test arrays.
func sortedArrayBasedOnMatches(testArrays:[[String]], control: [String]) -> [[String]]{
var final = [[String]].init()
var controlDict:[String: Int] = [:]
var orderDict:[Int: [[String]]] = [:] // the value is a array of arrays because there could be arrays with the same amount of matches.
for el in control{
if controlDict[el] == nil{
controlDict[el] = 1
}
else{
controlDict[el] = controlDict[el]! + 1
}
}
for tArr in testArrays{
var totalMatches = 0
var tDict = controlDict
for el in tArr{
if tDict[el] != nil && tDict[el] != 0 {
totalMatches += 1
tDict[el] = tDict[el]! - 1
}
}
if orderDict[totalMatches] == nil{
orderDict[totalMatches] = [[String]].init()
}
orderDict[totalMatches]?.append(tArr)
}
for key in Array(orderDict.keys).sorted(by: >) {
for arr in orderDict[key]! {
final.append(arr)
}
}
return final
}

Swift function not working inside another function

I'm new on this site but I've been struggling for several days about this issue I found. I wrote this code in order to solve a challenge of the site Codewars; the challenge consists in calculate the mean and the variance from some data about some fictional rainfalls (I attach the complete page on the bottom). In order to end this challenge I created a function to convert the data from this useless string into an array of Doubles. The weird thing is that the function if called outside the main one works properly but inside returns an empty array. I have no idea why is happening this. Thank you very much for every effort you'll put trying to explain me this.
This is the first part of the Codewars page that explain the callenge
This is the second one
//
// main.swift
// Prova
//
// Created by Lorenzo Santini on 13/06/18.
// Copyright © 2018 Lorenzo Santini. All rights reserved.
//
import Foundation
func mean(_ d: String,_ town: String) -> Double {
let arrayOfValues = obtainArrayOfMeasures(d, town)
var sum: Double = 0
for element in arrayOfValues {
sum += element
}
return sum / Double(arrayOfValues.count)
}
func variance(_ d: String,_ town: String) -> Double {
let meanValue: Double = mean(d, town)
//Here is the problem: when this function is called instead of returning the array containg all the measures for the selected city it returns an empty array
var arrayOfValues = obtainArrayOfMeasures(d, town)
var sum: Double = 0
for element in arrayOfValues {
sum += pow((element - meanValue), 2)
}
return sum / Double(arrayOfValues.count)
}
func isInt(_ char: Character) -> Bool {
switch char {
case "1","2","3","4","5","6","7","8","9":
return true
default:
return false
}
}
func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double]{
//The first array stores the Data string divided for city
var arrayOfString: [String] = []
//The second array stores the measures of rainfall of the town passed as argument for the function
var arrayOfMeasures: [Double] = []
//Split the d variable containg the data string in separated strings for each town and add it to the arrayOfString array
repeat {
let finalIndex = (data.index(of:"\n")) ?? data.endIndex
arrayOfString.append(String(data[data.startIndex..<finalIndex]))
let finalIndexToRemove = (data.endIndex == finalIndex) ? finalIndex : data.index(finalIndex, offsetBy: 1)
data.removeSubrange(data.startIndex..<finalIndexToRemove)
} while data.count != 0
//Find the string of the town passed as argument
var stringContainingTown: String? = nil
for string in arrayOfString {
if string.contains(town) {stringContainingTown = string; print("true")}
}
if stringContainingTown != nil {
var stringNumber = ""
var index = 0
//Add to arrayOfMeasures the measures of the selected town
for char in stringContainingTown! {
index += 1
if isInt(char) || char == "." {
stringNumber += String(char)
print(stringNumber)
}
if char == "," || index == stringContainingTown!.count {
arrayOfMeasures.append((stringNumber as NSString).doubleValue)
stringNumber = ""
}
}
}
return arrayOfMeasures
}
var data = "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9" + "\n" +
"London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9" + "\n" +
"Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7" + "\n" +
"NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2" + "\n" +
"Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5" + "\n" +
"Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2" + "\n" +
"Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4" + "\n" +
"Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4" + "\n" +
"Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7" + "\n" +
"Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7"
var prova = variance(data, "London")
The problem is that func obtainArrayOfMeasures modifies the global data
variable. When called the second time, data is an empty string.
An indicator for this problem is also that making the global data variable constant
let data = "Rome:..."
causes a compiler error at
data.removeSubrange(data.startIndex..<finalIndexToRemove)
// Cannot use mutating member on immutable value: 'data' is a 'let' constant
An immediate fix would be to operate on a local mutable copy:
func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double]{
var data = d
// ...
}
Note however that the function can be simplified to
func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double] {
let lines = d.components(separatedBy: .newlines)
guard let line = lines.first(where: { $0.hasPrefix(town)}) else {
return [] // No matching line found.
}
let entries = line.components(separatedBy: ",")
let numbers = entries.compactMap { Double($0.filter {".0123456789".contains($0) })}
return numbers
}
without mutating any values. You might also consider to return nil
or abort with fatalError() if no matching entry is found.

Finding The First Non-repeating Character algorithm Swift 4 (Looping over string only once)

I am trying to solve code fights interview practice questions, but I am stuck on how to solve this particular problem in swift. My first thought was to use a dictionary with the counts of each character, but then I would have to iterate over the string again to compare, so that doesn't work per the restrictions. Any help would be good. Thank you. Here is the problem and requirements:
Note: Write a solution that only iterates over the string once and uses O(1) additional memory, since this is what you would be asked to do during a real interview.
Given a string s, find and return the first instance of a non-repeating character in it. If there is no such character, return '_'
Here is the code I started with (borrowed from another post)
func firstNotRepeatingCharacter(s: String) -> Character {
var countHash:[Character:Int] = [:]
for character in s {
countHash[character] = (countHash[character] ?? 0) + 1
}
let nonRepeatingCharacters = s.filter({countHash[$0] == 1})
let firstNonRepeatingCharacter = nonRepeatingCharacters.first!
return firstNonRepeatingCharacter
}
firstNotRepeatingCharacter(s:"abacabad")
You can create a dictionary to store the occurrences and use first(where:) method to return the first occurrence that happens only once:
Swift 4
func firstNotRepeatingCharacter(s: String) -> Character {
var occurrences: [Character: Int] = [:]
s.forEach{ occurrences[$0, default: 0] += 1 }
return s.first{ occurrences[$0] == 1 } ?? "_"
}
Swift 3
func firstNotRepeatingCharacter(s: String) -> Character {
var occurrences: [Character:Int] = [:]
s.characters.forEach{ occurrences[$0] = (occurrences[$0] ?? 0) + 1}
return s.characters.first{ occurrences[$0] == 1 } ?? "_"
}
Another option iterating the string in reversed order and using an array of 26 elements to store the characters occurrences
func firstNotRepeatingCharacter(s: String) -> Character {
var chars = Array(repeating: 0, count: 26)
var characters: [Character] = []
var charIndex = 0
var strIndex = 0
s.characters.reversed().forEach {
let index = Int(String($0).unicodeScalars.first!.value) - 97
chars[index] += 1
if chars[index] == 1 && strIndex >= charIndex {
characters.append($0)
charIndex = strIndex
}
strIndex += 1
}
return characters.reversed().first { chars[Int(String($0).unicodeScalars.first!.value) - 97] == 1 } ?? "_"
}
Use a dictionary to store the character counts as well as where they were first encountered. Then, loop over the dictionary (which is constant in size since there are only so many unique characters in the input string, thus also takes constant time to iterate) and find the earliest occurring character with a count of 1.
func firstUniqueCharacter(in s: String) -> Character
{
var characters = [Character: (count: Int, firstIndex: Int)]()
for (i, c) in s.characters.enumerated()
{
if let t = characters[c]
{
characters[c] = (t.count + 1, t.firstIndex)
}
else
{
characters[c] = (1, i)
}
}
var firstUnique = (character: Character("_"), index: Int.max)
for (k, v) in characters
{
if v.count == 1 && v.firstIndex <= firstUnique.index
{
firstUnique = (k, v.firstIndex)
}
}
return firstUnique.character
}
Swift
Use dictionary, uniqueCharacter optional variable with unique characters array to store all uniquely present characters in the string , every time duplication of characters found should delete that character from unique characters array and same time it is the most first character then should update the dictionary with its count incremented , refer following snippet , how end of the iteration through all characters gives a FIRST NON REPEATED CHARACTER in given String. Refer following code to understand it properly
func findFirstNonRepeatingCharacter(string:String) -> Character?{
var uniqueChars:[Character] = []
var uniqueChar:Character?
var chars = string.lowercased().characters
var charWithCount:[Character:Int] = [:]
for char in chars{
if let count = charWithCount[char] { //amazon
charWithCount[char] = count+1
if char == uniqueChar{
uniqueChars.removeFirst()
uniqueChar = uniqueChars.first
}
}else{
charWithCount[char] = 1
uniqueChars.append(char)
if uniqueChar == nil{
uniqueChar = char
}
}
}
return uniqueChar
}
// Use
findFirstNonRepeatingCharacter(string: "eabcdee")