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
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)
}
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
}
}
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.
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"))
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"