Topological Sort Swift - swift

I'm trying to implement a topological sort in Swift using the following theory.
https://courses.cs.washington.edu/courses/cse326/03wi/lectures/RaoLect20.pdf
My code is:
func canFinish(_ numCourses: Int, _ prerequisites: [[Int]]) -> Bool {
guard (prerequisites.count > 0) else {return true}
var graph : [[Int]] = Array(repeating: [], count: numCourses + 1)
var inDegree : [Int] = Array(repeating: 0, count: numCourses + 1 )
for x in prerequisites {
graph[x[0]] = [x[1]]
inDegree[x[0]] += 1
}
for course in graph.enumerated() {
print ("To finish course \(course.offset) you must have finished \(course.element)")
}
for course in (inDegree.enumerated()) {
print ("Course \(course.offset) needs \(course.element) courses to be complete")
}
var outputArr = [Int]()
while let currentVertexIndx = (inDegree.enumerated().first { $0.element == 0 }?.offset) {
outputArr.append( currentVertexIndx )
for course in graph.enumerated() {
if (course.element.contains(currentVertexIndx)) {
inDegree[ course.offset ] -= 1
}
}
inDegree[currentVertexIndx] = -1
}
return outputArr.count >= numCourses
}
Tests with correct answers:
//canFinish(1, [[1,0]]) // true - to take course 1 you should have finished course 0
//canFinish(2, [[1,0],[0,1]]) // false - to take course 1 you have to have finished course 0, to take 0 you have to have finished course 1
//canFinish(1, []) // true
//canFinish(3, [[1,0],[2,0]]) // true
//canFinish(3, [[2,0],[2,1]]) // true
Test with incorrect answer
canFinish(10, [[5,6],[0,2],[1,7],[5,9],[1,8],[3,4],[0,6],[0,7],[0,3],[8,9]]) // true, but returns false
Question: My code does not work for the input above using the theory linked from Washington.edu. What is going wrong?

You should fill the graph correctly:
graph[x[0]] += [x[1]]
Which would yield the right result in the given example:
canFinish(10, [[5,6],[0,2],[1,7],[5,9],[1,8],[3,4],[0,6],[0,7],[0,3],[8,9]]) //true

Related

no response on stdout HackerRank Swift

Hello i practice on hackerRank using swift and now i have a problem. My code works great in swift playground, and return the expected result, but in HackerRank i have runtime error ~ no response on stdout ~ I've tried to reset code and refresh page. What could be the problem?
func diagonalDifference(arr: [[Int]]) -> Int {
// Write your code here
let rowNumber = arr[0][0]
var leftD = 0
var rightD = 0
for i in 1...rowNumber {
leftD += arr[i][i - 1]
}
var increasedNum = 0
for i in (1...rowNumber).reversed() {
rightD += arr[i][increasedNum]
increasedNum += 1
}
var absoluteDifference = leftD - rightD
if absoluteDifference < 0 {
absoluteDifference = absoluteDifference * -1
}
return absoluteDifference
}
Here is the challenge page:
https://www.hackerrank.com/challenges/diagonal-difference/problem
Your problem is a misunderstanding of what is passed to your diagonalDifference() function. The code which calls that function uses the first line of input to correctly size the array, but that value is not passed to your function in arr[0][0]. Instead, you should use arr.count to determine the dimensions of the array, then you should be indexing the array as 0..<arr.count.
To fix your code
change:
let rowNumber = arr[0][0]
to:
let rowNumber = arr.count
change:
leftD += arr[i][i - 1]
to:
leftD += arr[i][i]
And change both instances of
1...rowNumber
to:
0..<rowNumber
func diagonalDifference(arr: [[Int]]) -> Int {
var difference = 0
for i in 0..<arr.count {
difference += (arr[i][i] - arr[i][arr.count-1-i])
}
return Int(abs(difference))
}

Can't sort array: "Ambiguous reference to member '<'"

extension Array where Element: Numeric {
func closest(to givenValue: Element) -> Element {
let sorted = self.sorted(by: <)
let over = sorted.first(where: { $0 >= givenValue })!
let under = sorted.last(where: { $0 <= givenValue })!
let diffOver = over - givenValue
let diffUnder = givenValue - under
return (diffOver < diffUnder) ? over : under
}
}
In line 3 of this example code, Xcode gives me the incomprehensible error message Ambiguous reference to member '<', along with this great list:
What am I supposed to do here? I just want this array to get sorted.
You have to declare Element to be Comparable:
extension Array where Element: Numeric & Comparable {
In
let sorted = self.sorted(by: <)
you're not giving a boolean function for the function to use. Maybe try replacing it with :
let sorted = self.sorted(by: { $0 < $1 })
Problem is that you have defined your Element as Numeric only where > will work with Comparable.
Do it as:
extension Array where Element: Numeric, Element: Comparable {
func closest(to givenValue: Element) -> Element {
//... your code here ...
}
}
I was just running into a similar problem stemming from the type inference when chaining multiple higher order functions (sort, map, etc), when I found this post and I couldn't help but notice the inefficiency of your function.
Here is an example of how you can implement this same function using binary search, massively reducing the time it takes to execute on large datasets:
extension Array where Element: Numeric & Comparable {
func closest2(to target: Element) -> Element {
if target <= self[0] {
return self[0]
}
if target >= self[count - 1] {
return self[count - 1]
}
var i = 0
var j = count
var mid = 0
while i < j {
mid = (i + j) / 2
if self[mid] == target {
return self[mid]
}
if target < self[mid] {
if mid > 0 && target > self[mid - 1] {
return getClosest(val1: self[mid - 1], val2: self[mid], target: target)
}
j = mid
} else {
if mid < count - 1 && target < self[mid + 1] {
return getClosest(val1: self[mid], val2: self[mid + 1], target: target)
}
i = mid + 1
}
}
return self[mid]
}
private func getClosest(val1: Element, val2: Element, target: Element) -> Element {
return target - val1 > val2 - target ? val2 : val1
}
}

How to execute multiplications and/or divisions in the right order?

I am doing a simple calculator, but when performing the multiplication and division, my code doesn't make them a priority over plus and minus.
When doing -> 2 + 2 * 4, result = 16 instead of 10...
How to conform to the math logic inside my switch statement?
mutating func calculateTotal() -> Double {
var total: Double = 0
for (i, stringNumber) in stringNumbers.enumerated() {
if let number = Double(stringNumber) {
switch operators[i] {
case "+":
total += number
case "-":
total -= number
case "÷":
total /= number
case "×":
total *= number
default:
break
}
}
}
clear()
return total
}
Assuming you want a generalised and perhaps extensible algorithm for any arithmetic expression, the right way to do this is to use the Shunting Yard algorithm.
You have an input stream, which is the numbers and operators as the user typed them in and you have an output stream, which is the same numbers and operators but rearranged into reverse Polish notation. So, for example 2 + 2 * 4 would be transformed into 2 2 4 * + which is easily calculated by putting the numbers on a stack as you read them and applying the operators to the top items on the stack as you read them.
To do this the algorithm has an operator stack which can be visualised as a siding (hence "shunting yard") into which low priority operators are shunted until they are needed.
The general algorithm is
read an item from the input
if it is a number send it to the output
if the number is an operator then
while the operator on the top of the stack is of higher precedence than the operator you have pop the operator on the stack and send it to the output
push the operator you read from input onto the stack
repeat the above until the input is empty
pop all the operators on the stack into the output
So if you have 2 + 2 * 4 (NB top of the stack is on the left, bottom of the stack is on the right)
start:
input: 2 + 2 * 4
output: <empty>
stack: <empty>
step 1: send the 2 to output
input: + 2 * 4
output: 2
stack: <empty>
step 2: stack is empty so put + on the stack
input: 2 * 4
output: 2
stack: +
step 3: send the 2 to output
input: * 4
output: 2 2
stack: +
step 4: + is lower priority than * so just put * on the stack
input: 4
output: 2 2
stack: * +
step 5: Send 4 to output
input:
output: 2 2 4
stack: * +
step 6: Input is empty so pop the stack to output
input:
output: 2 2 4 * +
stack:
The Wikipedia entry I linked above has a more detailed description and an algorithm that can handle parentheses and function calls and is much more extensible.
For completeness, here is an implementation of my simplified version of the algorithm
enum Token: CustomStringConvertible
{
var description: String
{
switch self
{
case .number(let num):
return "\(num)"
case .op(let symbol):
return "\(symbol)"
}
}
case op(String)
case number(Int)
var precedence: Int
{
switch self
{
case .op(let symbol):
return Token.precedences[symbol] ?? -1
default:
return -1
}
}
var operation: (inout Stack<Int>) -> ()
{
switch self
{
case .op(let symbol):
return Token.operations[symbol]!
case .number(let value):
return { $0.push(value) }
}
}
static let precedences = [ "+" : 10, "-" : 10, "*" : 20, "/" : 20]
static let operations: [String : (inout Stack<Int>) -> ()] =
[
"+" : { $0.push($0.pop() + $0.pop()) },
"-" : { $0.push($0.pop() - $0.pop()) },
"*" : { $0.push($0.pop() * $0.pop()) },
"/" : { $0.push($0.pop() / $0.pop()) }
]
}
struct Stack<T>
{
var values: [T] = []
var isEmpty: Bool { return values.isEmpty }
mutating func push(_ n: T)
{
values.append(n)
}
mutating func pop() -> T
{
return values.removeLast()
}
func peek() -> T
{
return values.last!
}
}
func shuntingYard(input: [Token]) -> [Token]
{
var operatorStack = Stack<Token>()
var output: [Token] = []
for token in input
{
switch token
{
case .number:
output.append(token)
case .op:
while !operatorStack.isEmpty && operatorStack.peek().precedence >= token.precedence
{
output.append(operatorStack.pop())
}
operatorStack.push(token)
}
}
while !operatorStack.isEmpty
{
output.append(operatorStack.pop())
}
return output
}
let input: [Token] = [ .number(2), .op("+"), .number(2), .op("*"), .number(4)]
let output = shuntingYard(input: input)
print("\(output)")
var dataStack = Stack<Int>()
for token in output
{
token.operation(&dataStack)
}
print(dataStack.pop())
If you only have the four operations +, -, x, and ÷, you can do this by keeping track of a pendingOperand and pendingOperation whenever you encounter a + or -.
Then compute the pending operation when you encounter another + or -, or at the end of the calculation. Note that + or - computes the pending operation, but then immediately starts a new one.
I have modified your function to take the stringNumbers, operators, and initial values as input so that it could be tested independently in a Playground.
func calculateTotal(stringNumbers: [String], operators: [String], initial: Double) -> Double {
func performPendingOperation(operand: Double, operation: String, total: Double) -> Double {
switch operation {
case "+":
return operand + total
case "-":
return operand - total
default:
return total
}
}
var total = initial
var pendingOperand = 0.0
var pendingOperation = ""
for (i, stringNumber) in stringNumbers.enumerated() {
if let number = Double(stringNumber) {
switch operators[i] {
case "+":
total = performPendingOperation(operand: pendingOperand, operation: pendingOperation, total: total)
pendingOperand = total
pendingOperation = "+"
total = number
case "-":
total = performPendingOperation(operand: pendingOperand, operation: pendingOperation, total: total)
pendingOperand = total
pendingOperation = "-"
total = number
case "÷":
total /= number
case "×":
total *= number
default:
break
}
}
}
// Perform final pending operation if needed
total = performPendingOperation(operand: pendingOperand, operation: pendingOperation, total: total)
// clear()
return total
}
Tests:
// 4 + 3
calculateTotal(stringNumbers: ["3"], operators: ["+"], initial: 4)
7
// 4 × 3
calculateTotal(stringNumbers: ["3"], operators: ["×"], initial: 4)
12
// 2 + 2 × 4
calculateTotal(stringNumbers: ["2", "4"], operators: ["+", "×"], initial: 2)
10
// 2 × 2 + 4
calculateTotal(stringNumbers: ["2", "4"], operators: ["×", "+"], initial: 2)
8
// 17 - 2 × 3 + 10 + 7 ÷ 7
calculateTotal(stringNumbers: ["2", "3", "10", "7", "7"], operators: ["-", "×", "+", "+", "÷"], initial: 17)
22
First you have to search in the array to see if there is a ÷ or × sign.
Than you can just sum or subtract.
mutating func calculateTotal() -> Double {
var total: Double = 0
for (i, stringNumber) in stringNumbers.enumerated() {
if let number = Double(stringNumber) {
switch operators[i] {
case "÷":
total /= number
case "×":
total *= number
default:
break
}
//Remove the number from the array and make another for loop with the sum and subtract operations.
}
}
clear()
return total
}
This will work if you are not using complex numbers.
If you don't care speed, as it's running by a computer and you may use the machine way to handle it. Just pick one feasible calculate to do it and then repeat until every one is calculated.
Just for fun here. I use some stupid variable and function names.
func evaluate(_ values: [String]) -> String{
switch values[1] {
case "+": return String(Int(values[0])! + Int(values[2])!)
case "-": return String(Int(values[0])! - Int(values[2])!)
case "×": return String(Int(values[0])! * Int(values[2])!)
case "÷": return String(Int(values[0])! / Int(values[2])!)
default: break;
}
return "";
}
func oneTime(_ string: inout String, _ strings: [String]) throws{
if let first = try NSRegularExpression(pattern: "(\\d+)\\s*(\(strings.map{"\\\($0)"}.joined(separator: "|")))\\s*(\\d+)", options: []).firstMatch(in: string , options: [], range: NSMakeRange(0, string.count)) {
let tempResult = evaluate((1...3).map{ (string as NSString).substring(with: first.range(at: $0))})
string.replaceSubrange( Range(first.range(at: 0), in: string)! , with: tempResult)
}
}
func recursive(_ string: inout String, _ strings: [String]) throws{
var count : Int!
repeat{ count = string.count ; try oneTime(&string, strings)
} while (count != string.count)
}
func final(_ string: inout String, _ strings: [[String]]) throws -> String{
return try strings.reduce(into: string) { (result, signs) in
try recursive(&string, signs)
}}
var string = "17 - 23 + 10 + 7 ÷ 7"
try final(&string, [["×","÷"],["+","-"]])
print("result:" + string)
Using JeremyP method and the Shunting Yard algorithm was the way that worked for me, but I had some differences that had to do with the Operator Associativity(left or right priority) so I had to work with it and I developed the code, which is based on JeremyP answer but uses arrays.
First we have the array with the calculation in Strings, e.g.:
let testArray = ["10","+", "5", "*" , "4", "+" , "10", "+", "20", "/", "2"]
We use the function below to get the RPN version using the Shunting Yard algorithm.
func getRPNArray(calculationArray: [String]) -> [String]{
let c = calculationArray
var myRPNArray = [String]()
var operandArray = [String]()
for i in 0...c.count - 1 {
if c[i] != "+" && c[i] != "-" && c[i] != "*" && c[i] != "/" {
//push number
let number = c[i]
myRPNArray.append(number)
} else {
//if this is the first operand put it on the opStack
if operandArray.count == 0 {
let firstOperand = c[i]
operandArray.append(firstOperand)
} else {
if c[i] == "+" || c[i] == "-" {
operandArray.reverse()
myRPNArray.append(contentsOf: operandArray)
operandArray = []
let uniqOperand = c[i]
operandArray.append(uniqOperand)
} else if c[i] == "*" || c[i] == "/" {
let strongOperand = c[i]
//If I want my mult./div. from right(eg because of parenthesis) the line below is all I need
//--------------------------------
// operandArray.append(strongOperand)
//----------------------------------
//If I want my mult./div. from left
let lastOperand = operandArray[operandArray.count - 1]
if lastOperand == "+" || lastOperand == "-" {
operandArray.append(strongOperand)
} else {
myRPNArray.append(lastOperand)
operandArray.removeLast()
operandArray.append(strongOperand)
}
}
}
}
}
//when I have no more numbers I append the reversed operant array
operandArray.reverse()
myRPNArray.append(contentsOf: operandArray)
operandArray = []
print("RPN: \(myRPNArray)")
return myRPNArray
}
and then we enter the RPN array in the function below to calculate the result. In every loop we remove the numbers and the operand used before and we import the previous result and two "p" in the array so in the end we are left with the solution and an array of "p".
func getResultFromRPNarray(myArray: [String]) -> Double {
var a = [String]()
a = myArray
print("a: \(a)")
var result = Double()
let n = a.count
for i in 0...n - 1 {
if n < 2 {
result = Double(a[0])!
} else {
if a[i] == "p" {
//Do nothing else. Calculations are over and the result is in your hands!!!
} else {
if a[i] == "+" {
result = Double(a[i-2])! + Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else if a[i] == "-" {
result = Double(a[i-2])! - Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else if a[i] == "*" {
result = Double(a[i-2])! * Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else if a[i] == "/" {
result = Double(a[i-2])! / Double(a[i-1])!
a.insert(String(result), at: i-2)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.remove(at: i - 1)
a.insert("p", at: 0)
a.insert("p", at: 0)
} else {
// it is a number so do nothing and go the next one
}
}//no over yet
}//n>2
}//iterating
return result
}//Func

Group dictionary by key in Swift

I'm trying to implement a groupBy functionality where all the numbers of a nested list are grouped. My code so far:
struct MyClass {
var numbers: [Int]
...
}
var dict: [String : MyClass] = ...
let numbers = dict
.filter{ $0.0.containsString(searchString) }
.flatMap{ $0.1.numbers }
This yields me an Array of Ints. However I'd like to have a dictionary [Int : Int] with each unique number and the count of its occurence. So for example:
[1,2,3,4,1,2,2,1]
should be:
[1 : 2, 2 : 3, 3 : 1, 4 : 1]
I know there's a groupBy operator, but Swift doesn't seem to have one. I've tried with reduce:
func reducer(accumulator: [Int: Int], num: Int) -> [Int : Int] {
var acc = accumulator
acc[num]! += 1
return acc
}
filtered.reduce([:], combine: reducer)
But it crashes when I want to run it. Not sure why, I get a EXC_BAD_INSTRUCTION.
I'd appreciate any help.
let numbers = [1,2,3,4,1,2,2,1]
var results = [Int: Int]()
Set(numbers).forEach { number in results[number] = numbers.filter { $0 == number }.count }
print(results) // [2: 3, 3: 1, 1: 3, 4: 1]
Actually I'm not very sure if this is what you want. I just looked at your examples.
Using NSCountedSet:
var objects = [1,2,3,4,1,2,2,1]
let uniques = NSCountedSet(array: objects)
uniques.forEach { results[$0 as! Int] = uniques.countForObject($0) }
print(results) // [2: 3, 3: 1, 1: 3, 4: 1]
I would expect the crash to be ocurring on this line:
acc[num]! += 1
The first time this is called for a number, the entry doesn't exist in the dictionary yet so acc[num] is nil. Forcefully unwrapping it would cause a crash.
Not sure if this is the best solution but you can simple check for this case:
if (acc[num]) {
acc[num]! += 1
} else {
acc[num] = 1
}
Cleaner code from #vacawama in the comments:
acc[num] = (acc[num] ?? 0) + 1
Here's an extension to Array that does what you're asking:
extension Array where Element: Hashable {
var grouped: [Element:Int] {
var dict = [Element:Int]()
self.forEach { dict[$0] = (dict[$0] ?? 0) + 1 }
return dict
}
}
The key is the closure: { dict[$0] = (dict[$0] ?? 0) + 1 }.
It takes the current value in the array, tests to see if it's a key in the dictionary, returns the value for that key if it exists or 0 if it doesn't, then adds one and sets the key:value to be the pair of the current value and occurrences so far.
Example use:
[1,2,3,4,1,2,2,1].grouped // => [2: 3, 3: 1, 1: 3, 4: 1]
You need something like this:
if let _ = acc.indexForKey(num) {
acc[num]! += 1
}
else {
acc[num] = 1
}
It's sort of unclear what you're asking for, but here's a function that will take an array of ints and return a dictionary with the number as the key, and the count as the value:
func getDictionaryOfCounts(accumulator: [Int]) -> [Int : Int] {
var countingDictionary: [Int : Int] = [:]
accumulator.forEach { (value) in
if countingDictionary[value] != nil {
countingDictionary[value]! += 1
}
else{
countingDictionary[value] = 1
}
}
return countingDictionary
}

Count elements of array matching condition in Swift

I'm basically looking for the swift equivalent of the follow c++ code:
std::count_if(list.begin(), list.end(), [](int a){ return a % 2 == 0; }); // counts instances of even numbers in list
My problem isn't actually searching for even numbers, of course; simply the general case of counting instances matching a criterion.
I haven't seen a builtin, but would love to hear that I simply missed it.
Like this:
let a: [Int] = ...
let count = a.filter({ $0 % 2 == 0 }).count
An alternative to Aderstedt's version
let a = [ .... ]
let count = a.reduce(0){
(count, element) in
return count + 1 - element % 2
}
My intuition says my way will be faster because it doesn't require the creation of a second array. However, you'd need to profile both methods to be sure.
Edit
Following MartinR's comment about generalisation of the function, here it is
extension SequenceType
{
func countMatchingCondition(condition: (Self.Generator.Element) -> Bool) -> Int
{
return self.reduce(0, combine: { (count, e) in count + (condition(e) ? 1 : 0) })
}
}
let a = [1, 2, 3, 3, 4, 12].countMatchingCondition { $0 % 2 == 0 }
print("\(a)") // Prints 3
Default array:
let array: [Int] = [10, 10, 2, 10, 1, 2, 3]
filter(_:) method
let countOfTen = array.filter({ $0 == 10 }).count // 3
count(where:) method
Update: This Swift 5.0 feature was withdrawn in beta testing because it was causing performance issues for the type checker.
let countOfTen = array.count(where: { $0 == 10 }) // 3
You can use Collection.lazy to have the simplicity of Aderstedt's Answer but with O(1) space.
let array = [1, 2, 3]
let count = array.lazy.filter({ $0 % 2 == 0 }).count
The most compact reduce statement that will do this is:
let a = Array(1 ... 20)
let evencount = a.reduce(0) { $0 + ($1 % 2 == 0 ? 1 : 0) }
Reduce takes two variables: starts with 0 (var $0) then for every element in Array a (var $1) if the value is divisible by 2 with no remainder then add one to your count.
This is also efficient as it does not create an additional array unlike using a.filter(){}.count .
You can also do this with reduce()
let a = Array(1 ... 20)
let evenCount = a.reduce(0) { (accumulator, value) -> Int in
guard value % 2 == 0 else { return accumulator }
return accumulator + 1
}
Almost everything you want to do with the map() and filter functions can actually be done with a reduce although it's not always the most readable.
Swift 5 or later:
public extension Sequence {
func occurrences(where predicate: (Element) throws -> Bool) rethrows -> Int {
try reduce(0) { try predicate($1) ? $0 + 1 : $0 }
}
}
public extension Sequence where Element: Equatable {
func occurrences(of element: Element) -> Int {
reduce(0) { element == $1 ? $0 + 1 : $0 }
}
}
let multiplesOf2 = [1,2,3,4,4,5,4,5].occurrences{$0.isMultiple(of: 2)} // 4
"abcdeabca".occurrences(of: "a") // 3
extension BinaryInteger {
var isOdd: Bool { !isMultiple(of: 2) }
var isEven: Bool { isMultiple(of: 2) }
}
(-4).isOdd // false
(-3).isOdd // true
(-2).isOdd // false
(-1).isOdd // true
0.isOdd // false
1.isOdd // true
2.isOdd // false
3.isOdd // true
4.isOdd // false
(-4).isEven // true
(-3).isEven // false
(-2).isEven // true
(-1).isEven // false
0.isEven // true
1.isEven // false
2.isEven // true
3.isEven // false
4.isEven // true
let odds = [1,2,3,4,4,5,5,11].occurrences(where: \.isOdd) // 5
let evens = [1,2,3,4,4,5,5,11].occurrences(where: \.isEven) // 3