Union-find: largest component size by common factor algorithm gives different results on every run - swift

I was practicing data structure algorithm and made a Union - Find solution for the question.
The problem is, I think the code seems ok, but when I run it on Xcode playground, it shows different answers for the same input.
For example, I put an array [4, 6, 15, 35] in the function largestComponentSize, then it shows 2, 3, or 4 as the answer. I don't understand what's happening behind.
class Solution {
var uf = UnionFind()
func largestComponentSize(_ nums: [Int]) -> Int {
var maxNum:Int = 0
var numFactorMap = [Int:Int]()
var factorAdded = Set<Int>()
for num in nums {
var pFactors = getPrimeFactors(num)
numFactorMap[num] = pFactors[0]
for (i, val) in pFactors.enumerated() {
if !factorAdded.contains(val) {
uf.addSet(val)
factorAdded.insert(val)
}
if i > 0 {
uf.union(pFactors[i-1], val)
}
}
}
var groupCountMap = [Int:Int]()
for num in nums {
var groupId = uf.find(numFactorMap[num]!)!
if groupCountMap.keys.contains(groupId) {
groupCountMap[groupId]! += 1
} else {
groupCountMap[groupId] = 1
}
maxNum = max(maxNum, groupCountMap[groupId]!)
}
return maxNum
}
func getPrimeFactors(_ num: Int) -> [Int] {
var ans:Set<Int> = []
if num == 1 {
return []
}
var crrNum = num
var deno = 2
while crrNum >= deno {
if crrNum % deno == 0 {
ans.insert(deno)
crrNum = crrNum / deno
} else {
deno = deno + 1
}
}
return Array(ans)
}
class UnionFind {
var index = [Int: Int]()
var parent: [Int]
var size: [Int]
init() {
parent = []
size = []
}
func addSet(_ ele: Int) {
index[ele] = parent.count
parent.append(parent.count)
size.append(1)
}
func getSetSize(_ ele: Int) -> Int {
if let found = find(ele) {
return size[found]
}
return 0
}
func find(_ ele: Int) -> Int? {
if let indexOfEle = index[ele] {
if parent[indexOfEle] == indexOfEle {
return indexOfEle
} else {
if let found = find(parent[indexOfEle]) {
parent[indexOfEle] = found
}
return parent[indexOfEle]
}
} else {
return nil //never come here
}
}
func union(_ first: Int, _ second: Int) {
guard let indexOfFirst = index[first], let indexOfSecond = index[second] else {
return
}
if parent[indexOfFirst] == parent[indexOfSecond] {
return
}
var indexOfLarger = indexOfFirst
var indexOfSmaller = indexOfSecond
if size[indexOfFirst] < size[indexOfSecond] {
indexOfLarger = indexOfSecond
indexOfSmaller = indexOfFirst
}
parent[indexOfSmaller] = indexOfLarger
size[indexOfLarger] += size[indexOfSmaller]
return
}
}
}
var sol = Solution()
var nums = [4, 6, 15, 35]
var ans = sol.largestComponentSize(nums)
Thank you for your help in advance!
I just tried it on Xcode playground.

Related

Is it possible in Swift to return an Int and a list of int at the same time?

I have to write a function in Swift where I need create a list of int if the counter is different to 0.
Here is my code in Swift :
func compteurZeros(cellule:[[Int]]) -> (compteur:Int, liste:(Int))
{
var compteur = 0;
for i in 0...2
{
for j in 0...2
{
if(cellule[i][j] == 0)
{
compteur = compteur+1
}
}
}
print(compteur)
if (compteur != 0)
{
for i in 0..<(compteur) {
var liste:(Int)
}
}
return (compteur, liste!)
}
But, in the return, I've got this error :
error: use of unresolved identifier 'liste'
return (compteur, liste!)
Thank you for your answer.
You need to change your function somewhat so that it returns an [[Int]] as the second element in the tuple
func compteurZeros(cellule:[[Int]]) -> (compteur:Int, liste:[[Int]]) {
var compteur = 0;
for i in 0...2
{
for j in 0...2
{
if(cellule[i][j] == 0)
{
compteur = compteur+1
}
}
}
var liste = [[Int]]()
if (compteur != 0)
{
for i in 0..<(compteur) {
liste.append([])
}
}
return (compteur, liste)
}
Now this code is not the best so it can be improved by skipping the loops
func compteurZeros(cellule:[[Int]]) -> (compteur:Int, liste:[[Int]]) {
let compteur = cellule.flatMap {$0}.filter {$0 == 0}.count
let liste:[[Int]] = Array(repeating: [], count: compteur)
return (compteur, liste)
}
Since the value compteur is redundant this can be further simplified to
func compteurZeros(cellule:[[Int]]) -> [[Int]] {
return Array(repeating: [], count: cellule.flatMap {$0}.filter {$0 == 0}.count)
}

Levenshtein distance in Swift3

I'm using a tutorial from Rosetta Code to calculate Levenshtein distance. It seems their code is in Swift2 so I get this error Binary operator '+' cannot be applied to operands of type '[Int]' and 'Repeated<String.CharacterView>' when doing this: var cur = [i + 2] + empty where let empty = repeatElement(s, count: 0). How can I go about this?
There were a couple of changes to make.
The construction of the Array empty.
enumerate() is now enumerated()
successor() doesn't exist anymore so I replaced it with +1
So the function is now
Swift 4:
func levDis(_ w1: String, _ w2: String) -> Int {
let empty = [Int](repeating:0, count: w2.count)
var last = [Int](0...w2.count)
for (i, char1) in w1.enumerated() {
var cur = [i + 1] + empty
for (j, char2) in w2.enumerated() {
cur[j + 1] = char1 == char2 ? last[j] : min(last[j], last[j + 1], cur[j]) + 1
}
last = cur
}
return last.last!
}
Swift 3:
func levDis(w1: String, w2: String) -> Int {
let (t, s) = (w1.characters, w2.characters)
let empty = Array<Int>(repeating:0, count: s.count)
var last = [Int](0...s.count)
for (i, tLett) in t.enumerated() {
var cur = [i + 1] + empty
for (j, sLett) in s.enumerated() {
cur[j + 1] = tLett == sLett ? last[j] : min(last[j], last[j + 1], cur[j])+1
}
last = cur
}
return last.last!
}
Updated and improved answer to Swift 4, based on #Spads answer.
extension String {
func levenshteinDistanceScore(to string: String, ignoreCase: Bool = true, trimWhiteSpacesAndNewLines: Bool = true) -> Float {
var firstString = self
var secondString = string
if ignoreCase {
firstString = firstString.lowercased()
secondString = secondString.lowercased()
}
if trimWhiteSpacesAndNewLines {
firstString = firstString.trimmingCharacters(in: .whitespacesAndNewlines)
secondString = secondString.trimmingCharacters(in: .whitespacesAndNewlines)
}
let empty = [Int](repeating:0, count: secondString.count)
var last = [Int](0...secondString.count)
for (i, tLett) in firstString.enumerated() {
var cur = [i + 1] + empty
for (j, sLett) in secondString.enumerated() {
cur[j + 1] = tLett == sLett ? last[j] : Swift.min(last[j], last[j + 1], cur[j])+1
}
last = cur
}
// maximum string length between the two
let lowestScore = max(firstString.count, secondString.count)
if let validDistance = last.last {
return 1 - (Float(validDistance) / Float(lowestScore))
}
return 0.0
}
}
infix operator =~
func =~(string: String, otherString: String) -> Bool {
return string.levenshteinDistanceScore(to: otherString) >= 0.85
}
func ~=(string: String, otherString: String) -> Bool {
return string.levenshteinDistanceScore(to: otherString) >= 0.85
}
Since #Daniel Illescas answer is not working, here is working version with Int return type and with assert.
extension String {
func levenshteinDistance(to string: String, ignoreCase: Bool = true, trimWhiteSpacesAndNewLines: Bool = true) -> Int {
var firstString = self
var secondString = string
if ignoreCase {
firstString = firstString.lowercased()
secondString = secondString.lowercased()
}
if trimWhiteSpacesAndNewLines {
firstString = firstString.trimmingCharacters(in: .whitespacesAndNewlines)
secondString = secondString.trimmingCharacters(in: .whitespacesAndNewlines)
}
let empty = [Int](repeating: 0, count: secondString.count)
var last = [Int](0...secondString.count)
for (i, tLett) in firstString.enumerated() {
var cur = [i + 1] + empty
for (j, sLett) in secondString.enumerated() {
cur[j + 1] = tLett == sLett ? last[j] : Swift.min(last[j], last[j + 1], cur[j]) + 1
}
last = cur
}
if let validDistance = last.last {
return validDistance
}
assertionFailure()
return 0
}
}

Swift Dijkstra Algorithm Error (EXC_BAD_INSTRUCTION)

So I've built a swift playground that uses Dijkstra's algorithm to find the shortest route. However, I can't seem to manipulate my txt file so that my function will work in every case. It only works for a select few pathways. Whenever I map out a pathway I believe should work, it responds with: Execution was interrupted, reason: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0).
How can I manipulate my txt file or my function/file manipulation to take my txt file input? (Where error occurred is marked -- near the bottom)
Usually the error occurs when trying to build a route backwards.
Ex: a1 to a3 works
Ex: a3 to a1 does not work
Code:
import Foundation
// Extensions
extension Array {
func each<U>(closure:(Element)->U?)->U? {
for i in self {
let returnVal = closure(i)
if (returnVal != nil) { return returnVal }
}
return nil
}
}
extension Int {
func times(closure:(Int)->Void) {
for i in 0..<self { closure(i) }
}
}
// Structs
struct Edge {
var wt: Double
var desV: Room
}
struct Graph { var vertices:[Room] }
// Room Class
class Room: Hashable {
var name: String?
var neighbors: [Edge] = []
var hashValue: Int {
get { return name!.hashValue }
}
init(){}
convenience init(name:String) {
self.init()
self.name = name
}
func distanceToRoom(targetRoom:Room) -> Edge? {
return self.neighbors.each({ (edge:Edge) -> Edge? in
if (edge.desV == targetRoom) {
return edge
}
return nil
})
}
}
// Functions
func == (lhs:Room, rhs:Room) -> Bool { return lhs.hashValue == rhs.hashValue }
func say( a:String ) { print( a, terminator:"") }
func dijkstra(graph:Graph, target:Room) -> [Room:Room] {
var queue = graph.vertices
var distances:[Room:Double] = [:]
var previousPaths:[Room:Room] = [:]
let currentRoom:Room = queue[0]
queue.each {(element:Room) -> Void? in
distances[element] = Double.infinity
previousPaths[element] = nil
return nil
}
distances[currentRoom] = 0
while (queue.count > 0) {
var closestNode:Room? = nil
let wt:Double = Double.infinity
queue.each({ (Room:Room) -> Void? in
if (closestNode == nil || wt < distances[Room]!) {
closestNode = Room
}
return nil
})
if (closestNode! == target) {
return previousPaths
}
let nodeIndex:Int? = queue.indexOf(closestNode!)
queue.removeAtIndex(nodeIndex!)
if (closestNode?.neighbors != nil && closestNode?.neighbors.count > 0) {
closestNode?.neighbors.each({(neighbor:Edge) -> Void? in
let wt = distances[closestNode!]! + closestNode!.distanceToRoom(neighbor.desV)!.wt
if wt < distances[neighbor.desV] {
distances[neighbor.desV] = wt
previousPaths[neighbor.desV] = closestNode!
}
return nil
})
}
}
return previousPaths
}
// File Management
//let url = NSURL(string:"file:///Users/caleb/Documents/Xcode/CRHS/CRHS/dtb.txt")!
let url = NSURL(string: "file:///Users/caleb/Desktop/rooms.txt")!
let data = NSData(contentsOfURL: url)
let sdata = String(data: data!, encoding: NSUTF8StringEncoding)
let dataArray = sdata!.characters.split{$0 == "\n"}.map(String.init)
var rooms = [String:Room]()
print("data:\n-------")
for i in 0 ..< dataArray.count {
let conn = dataArray[i].characters.split{$0 == "\t"}.map(String.init)
var room1: Room
if ( rooms[conn[0]] == nil ) {
room1 = Room(name: conn[0])
} else {
room1 = rooms[conn[0]]!
}
let room2 = Room(name: conn[2])
let edwt = (conn[1] as NSString).doubleValue
var edge = Edge(wt: edwt, desV: room2)
if room1.neighbors.count == 0 {
room1.neighbors = [ edge ]
} else {
var found: Bool = false
for e in room1.neighbors {
if ( e.desV.name == edge.desV.name ) {
found = true
}
}
if ( found == false ) {
room1.neighbors.append(edge)
}
}
rooms[conn[0]] = room1
}
for (nam,room) in rooms {
print(nam)
print("----")
for n in room.neighbors {
if let un = n.desV.name {
print( un, terminator: " weight: ")
}
print( n.wt )
}
print("\n")
}
var namessofrooms = rooms.map { $0.0 }
var roomsofrooms = rooms.map { $0.1 }
print("Rooms:")
print(rooms)
print("-------\n")
// Calculating
var source = rooms["a1"]!
var target = rooms["a4"]!
roomsofrooms.append(source)
var reversedRooms: Array = roomsofrooms.reverse()
reversedRooms.append(target)
var graph = Graph(vertices: reversedRooms)
var paths = dijkstra(graph, target: target)
var pathVertices:[Room] = [target]
var child = target
while (child != source) {
print(child.name)
print(":::::")
child = paths[child]! //Error occurs here
print(child.name)
pathVertices.append(child)
}
var pathString:[String] = pathVertices.reverse().map { (Room:Room) -> String in
return Room.name!
}
print("solution:\n-------")
print(pathString)
Below is the file I input:
a1 1 a2
a2 1 a3
a3 1 a4
If I input the following file the code above will not work:
a1 1 a2
a2 1 a3
a3 1 a4
a4 1 a5
(Update: File Map Clarification)
First column is the first room, second is the weight between the rooms, third is the room connected to the first.

LeetCode 299. Bulls and Cows, Swift Code

The OJ page is: 299. Bulls and Cows, Swift Code
My Swift Code is:
func getHint(secret: String, _ guess: String) -> String
{
let count = secret.characters.count
var ans = ""
var countA = 0
var countB = 0
var numsCount = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for i in 0 ..< count
{
let curSecretIndex = secret.startIndex.advancedBy(i)
let curGuessIndex = guess.startIndex.advancedBy(i)
if secret[curSecretIndex] == guess[curGuessIndex]
{
countA += 1
}
else
{
let curSecretNum = Int(String(secret[curSecretIndex]))!
let curGuessNum = Int(String(guess[curGuessIndex]))!
if numsCount[curSecretNum] > 0
{
countB += 1
}
if numsCount[curGuessNum] < 0
{
countB += 1
}
numsCount[curSecretNum] -= 1
numsCount[curGuessNum] += 1
}
}
ans = String(countA) + "A" + String(countB) + "B"
return ans
}
The result it 'Time Limit Exceeded' when running the case:
"6342125515600209181500897947396070342608717883958593622428977819470145518981094482423670643602640743135109789842055897996388630146186752661167826378847934464616412304716111808304498782005822162883686211337836911445498225004774354586168838560300965168000411392051373086314099651372076489284613220040070817961103856849197569739439674339914883676284322398392068700339678002599137137279304395401279115346633764844174685348142841166612675248803215000249557405129671377750613405565000541484366826871257668988459106913268432182614110919996681746630972155917317871065083728781479655332598828637865325616648485574880796687189161689539391392553041342138974604486863793131125744568750189486989526831390549186801009323526430712299903383659261758477604285513561656265905238724724774327396452598472436892619082685728038313372432807929513713314602774582152430611189205157910570001968051407417723280898588867721259234562110839321097595400391525102339288526258798825449826942020614695348904788907661932993430488593552", "2029388157754123013579930824032835962698439709529058700566544658243563588105123607416485416240508396898633255420749620114578170997813662130792145648053315140036623409978307287859342924657549449161362779317296010762442132229389529024391729227555488965589257218766928737602934082420388840064521623805135789781907460246852282793026912370042044884703394961008247101686942091465646505425818246546319109188403876239911011831539311377016115552962442767907020896812732576449580620680669604714802174904961265522985701150408238410077557827782193833638029934745703495039208558090425795228240968930462177363142995202879750991368837565022531005343218914976811148294727154364844319794156224312278949985742616475018653587238917107571280831446981869075410523704462504535667036707669945712843129399060874345018414837070546836481691874559666339572723901027743847187340764130312322743860946054990407323560232897592869469337005471407593834874319157599015450827399558773751402417232829362967857998884017081049757447739946"
How can I improve the performance?
Anyone help? THANKS!
Not sure how did you get the 'Time Limit Exceeded'. Try this in playground:
import Foundation
func bowsAndBulls (guess: String, secret: String) -> String {
if guess.characters.count != secret.characters.count {
return "ERROR"
}
//use counter variables works too
var countA = [String]()
var countB = [String]()
for i in 0..<guess.characters.count {
let start = guess.startIndex.advancedBy(i)
let end = guess.startIndex.advancedBy(i+1)
let single = guess.substringWithRange(start..<end)
if secret.containsString(single) {
if secret.substringWithRange(start..<end) == single {
countA.append(single)
}else{
countB.append(single)
}
}
}
return String(countA.count) + "A" + String(countB.count) + "B"
}
print(bowsAndBulls("5234", secret: "5346"))

Subscript of a struct doesn't set values when created as an implicitly unwrapped optional

Why can't I change the the "numbers" array using subscripts when "Foo" is an implicitly unwrapped optional?
struct Foo {
var numbers = [0,0,0]
subscript(index: Int) -> Int {
get { return self.numbers[index] }
set { self.numbers[index] = newValue }
}
}
var fooA:Foo!
fooA = Foo()
fooA[1] = 1 // does not change numbers array
fooA[1] // returns 0
fooA.numbers[1] = 1 // this works
fooA[1] // returns 1
var fooB:Foo!
fooB = Foo()
fooB![1] = 1 // this works
fooB![1] // returns 1
For some reason it works when I make "Foo" a class (called "Goo" below)
class Goo {
var numbers = [0,0,0]
subscript(index: Int) -> Int {
get { return self.numbers[index] }
set { self.numbers[index] = newValue }
}
}
var goo:Goo!
goo = Goo()
goo[1] = 1 // this works
goo[1] // returns 1
it looks like a bug (or i miss something important), check this
struct Foo {
var numbers = [0,0,0]
subscript(index: Int) -> Int {
get {
return self.numbers[index]
}
set {
numbers[index] = newValue
}
}
}
var fooA:Foo! = Foo()
// here is the difference
fooA?[1] = 1
fooA[1] // 1
fooA.numbers[1] = 1
fooA[1] // 1
more 'complex' experiment
struct Foo {
var numbers = [0,0,0]
subscript(index: Int) -> Int {
get {
return numbers[index]
}
set {
print(numbers[index],newValue)
numbers[index] = newValue
print(numbers[index])
}
}
}
var fooA:Foo! = Foo()
fooA[1] = 1
fooA[1] // 0
// but prints
// 0 1
// 1
for more 'fun'
var fooA:Foo! = Foo()
if var foo = fooA {
foo[1] = 1
print(foo)
}
prints
"Foo(numbers: [0, 1, 0])\n"