Find longest common substring of array of Strings - ios

In my Swift 3.0 app, I want to determine the best name for something by finding the longest common substring of 6 to 12 strings.
Example strings:
ON/OFF office lights
DIM office lights
VALUE office lights
FB office lights
FB VALUE office lights
Desired output:
office lights
I've come across multiple StackOverflow answers for the longest subsequence but haven't been able to adapt any of them to my needs..
Any help would be greatly appreciated!

I converted Java & C++ code into Swift 3 , collected from GeeksForGeeks Longest Common Subsequence & Longest Common Substring.
It works !
class LongestCommon
{
// Returns length of LCS for X[0..m-1], Y[0..n-1]
private static func lcSubsequence(_ X : String , _ Y : String ) -> String
{
let m = X.characters.count
let n = Y.characters.count
var L = Array(repeating: Array(repeating: 0, count: n + 1 ) , count: m + 1)
// Following steps build L[m+1][n+1] in bottom up fashion. Note
// that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1]
for i in stride(from: 0, through: m, by: 1)
{
for j in stride(from: 0, through: n, by: 1)
{
if i == 0 || j == 0
{
L[i][j] = 0;
}
else if X[X.index( X.startIndex , offsetBy: (i - 1) )] == Y[Y.index( Y.startIndex , offsetBy: (j - 1) )]
{
L[i][j] = L[i-1][j-1] + 1
}
else
{
L[i][j] = max(L[i-1][j], L[i][j-1])
}
}
}
// Following code is used to print LCS
var index = L[m][n]
// Create a character array to store the lcs string
var lcs = ""
// Start from the right-most-bottom-most corner and
// one by one store characters in lcs[]
var i = m
var j = n
while (i > 0 && j > 0)
{
// If current character in X[] and Y are same, then
// current character is part of LCS
if X[X.index( X.startIndex , offsetBy: (i - 1) )] == Y[Y.index( Y.startIndex , offsetBy: (j - 1) )]
{
lcs.append(X[X.index( X.startIndex , offsetBy: (i - 1) )])
i-=1
j-=1
index-=1
}
// If not same, then find the larger of two and
// go in the direction of larger value
else if (L[i-1][j] > L[i][j-1])
{
i-=1
}
else
{
j-=1
}
}
// return the lcs
return String(lcs.characters.reversed())
}
// Returns length of LCS for X[0..m-1], Y[0..n-1]
private static func lcSubstring(_ X : String , _ Y : String ) -> String
{
let m = X.characters.count
let n = Y.characters.count
var L = Array(repeating: Array(repeating: 0, count: n + 1 ) , count: m + 1)
var result : (length : Int, iEnd : Int, jEnd : Int) = (0,0,0)
// Following steps build L[m+1][n+1] in bottom up fashion. Note
// that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1]
for i in stride(from: 0, through: m, by: 1)
{
for j in stride(from: 0, through: n, by: 1)
{
if i == 0 || j == 0
{
L[i][j] = 0;
}
else if X[X.index( X.startIndex , offsetBy: (i - 1) )] == Y[Y.index( Y.startIndex , offsetBy: (j - 1) )]
{
L[i][j] = L[i-1][j-1] + 1
if result.0 < L[i][j]
{
result.length = L[i][j]
result.iEnd = i
result.jEnd = j
}
}
else
{
L[i][j] = 0 //max(L[i-1][j], L[i][j-1])
}
}
}
// Following code is used to print LCS
let lcs = X.substring(with: X.index(X.startIndex, offsetBy: result.iEnd-result.length)..<X.index(X.startIndex, offsetBy: result.iEnd))
// return the lcs
return lcs
}
// driver program
class func subsequenceOf(_ strings : [String] ) -> String
{
var answer = strings[0] // For on string answer is itself
for i in stride(from: 1, to: strings.count, by: 1)
{
answer = lcSubsequence(answer,strings[i])
}
return answer
}
class func substringOf(_ strings : [String] ) -> String
{
var answer = strings[0] // For on string answer is itself
for i in stride(from: 1, to: strings.count, by: 1)
{
answer = lcSubstring(answer,strings[i])
}
return answer
}
}
Usage :
let strings = ["ON/OFF office lights",
"DIM office lights",
"VALUE office lights",
"FB office lights",
"FB VALUE office lights"]
print(LongestCommon.subsequenceOf(strings))
print(LongestCommon.substringOf(strings))

Related

Mathematic calculation using array of numbers and array of arithmetic operators in swift [duplicate]

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

Hackerrank New Year Chaos Swift

I am trying to solve Hackerrank's New Year Chaos problem in Swift. https://www.hackerrank.com/challenges/new-year-chaos/problem
It is about finding the number of bribes people made on a line waiting for a roller coaster ride. For example, there is a total of 3 bribes in this list [2, 1, 5, 3, 4].
Person 2 bribed person 1.
Person 5 bribed person 3 and 4.
If there are more than 2 bribes by a person, the line becomes "Too chaotic".
I was able to get an exponential solution. However, I want to make it linear.
func minimumBribes(q: [Int]) -> Void {
var bribeCount = 0
var chaotic = false
// for i in 0..<q.count {
// if q[i] - (i + 1) > 2 {
// chaotic = true
// break
// }
//
// for j in i + 1..<q.count {
// if q[i] > q[j] {
// bribeCount += 1
// }
// }
// }
var i = 0
while i < q.count - 1 {
if q[i] - (i + 1) > 2 {
chaotic = true
break
} else if q[i] > i + 1 {
bribeCount += (q[i] - (i + 1))
i += 1
} else if q[i] <= i + 1 && q[i] > q[i + 1] && q.indices.contains(i + 1) {
bribeCount += 1
i += 1
} else { // q[i] < q[i + 1]
i += 1
}
}
if chaotic {
print("Too chaotic")
} else {
print(bribeCount)
}
}
I commented out the exponential solution, which works. But the linear solution does not work and I cannot find out why. It works with the following arrays, [3,2,1,6,5,4], [2,5,1,3,4], [1,2,5,3,7,8,6,4], [1,3,4,2,7,6,5,9,8,11,10,14,13,12].
But there is a really long array in one of the test cases of the problem, which I do not get the correct answer with my linear solution.
For this long array, I get 966 with my exponential solution but the linear solution prints 905.
[2,1,5,6,3,4,9,8,11,7,10,14,13,12,17,16,15,19,18,22,20,24,23,21,27,28,25,26,30,29,33,32,31,35,36,34,39,38,37,42,40,44,41,43,47,46,48,45,50,52,49,51,54,56,55,53,59,58,57,61,63,60,65,64,67,68,62,69,66,72,70,74,73,71,77,75,79,78,81,82,80,76,85,84,83,86,89,90,88,87,92,91,95,94,93,98,97,100,96,102,99,104,101,105,103,108,106,109,107,112,111,110,113,116,114,118,119,117,115,122,121,120,124,123,127,125,126,130,129,128,131,133,135,136,132,134,139,140,138,137,143,141,144,146,145,142,148,150,147,149,153,152,155,151,157,154,158,159,156,161,160,164,165,163,167,166,162,170,171,172,168,169,175,173,174,177,176,180,181,178,179,183,182,184,187,188,185,190,189,186,191,194,192,196,197,195,199,193,198,202,200,204,205,203,207,206,201,210,209,211,208,214,215,216,212,218,217,220,213,222,219,224,221,223,227,226,225,230,231,229,228,234,235,233,237,232,239,236,241,238,240,243,242,246,245,248,249,250,247,244,253,252,251,256,255,258,254,257,259,261,262,263,265,264,260,268,266,267,271,270,273,269,274,272,275,278,276,279,277,282,283,280,281,286,284,288,287,290,289,285,293,291,292,296,294,298,297,299,295,302,301,304,303,306,300,305,309,308,307,312,311,314,315,313,310,316,319,318,321,320,317,324,325,322,323,328,327,330,326,332,331,329,335,334,333,336,338,337,341,340,339,344,343,342,347,345,349,346,351,350,348,353,355,352,357,358,354,356,359,361,360,364,362,366,365,363,368,370,367,371,372,369,374,373,376,375,378,379,377,382,381,383,380,386,387,384,385,390,388,392,391,389,393,396,397,394,398,395,401,400,403,402,399,405,407,406,409,408,411,410,404,413,412,415,417,416,414,420,419,422,421,418,424,426,423,425,428,427,431,430,429,434,435,436,437,432,433,440,438,439,443,441,445,442,447,444,448,446,449,452,451,450,455,453,454,457,456,460,459,458,463,462,464,461,467,465,466,470,469,472,468,474,471,475,473,477,476,480,479,478,483,482,485,481,487,484,489,490,491,488,492,486,494,495,496,498,493,500,499,497,502,504,501,503,507,506,505,509,511,508,513,510,512,514,516,518,519,515,521,522,520,524,517,523,525,526,529,527,531,528,533,532,534,530,537,536,539,535,541,538,540,543,544,542,547,548,545,549,546,552,550,551,554,553,557,555,556,560,559,558,563,562,564,561,567,568,566,565,569,572,571,570,575,574,577,576,579,573,580,578,583,581,584,582,587,586,585,590,589,588,593,594,592,595,591,598,599,596,597,602,603,604,605,600,601,608,609,607,611,612,606,610,615,616,614,613,619,618,617,622,620,624,621,626,625,623,628,627,631,630,633,629,635,632,637,636,634,638,640,642,639,641,645,644,647,643,646,650,648,652,653,654,649,651,656,658,657,655,661,659,660,663,664,666,662,668,667,670,665,671,673,669,672,676,677,674,679,675,680,678,681,684,682,686,685,683,689,690,688,687,693,692,691,696,695,698,694,700,701,702,697,704,699,706,703,705,709,707,711,712,710,708,713,716,715,714,718,720,721,719,723,717,722,726,725,724,729,728,727,730,733,732,735,734,736,731,738,737,741,739,740,744,743,742,747,746,745,750,748,752,749,753,751,756,754,758,755,757,761,760,759,764,763,762,767,765,768,766,771,770,769,774,773,776,772,778,777,779,775,781,780,783,784,782,786,788,789,787,790,785,793,791,792,796,795,794,798,797,801,799,803,800,805,802,804,808,806,807,811,809,810,814,812,813,817,816,819,818,815,820,821,823,822,824,826,827,825,828,831,829,830,834,833,836,832,837,839,838,841,835,840,844,842,846,845,843,849,847,851,850,852,848,855,854,853,857,856,858,861,862,860,859,863,866,865,864,867,870,869,868,872,874,875,871,873,877,878,876,880,881,879,884,883,885,882,888,886,890,891,889,893,887,895,892,896,898,894,899,897,902,901,903,905,900,904,908,907,910,909,906,912,911,915,913,916,918,914,919,921,917,923,920,924,922,927,925,929,928,926,932,931,934,930,933,935,937,939,940,938,936,943,944,942,941,947,946,948,945,951,950,949,953,952,956,954,958,957,955,961,962,963,959,964,966,960,965,969,968,971,967,970,974,972,976,973,975,979,977,981,982,978,980,983,986,984,985,989,988,987,990,993,991,995,994,997,992,999,1000,996,998]
Please help me figure out what is wrong with my solution. Thanks in advance!!
Here is my solution which passes all the test cases :)
func minimumBribes(q: [Int]) -> Void {
var bCount = 0
var isChaotic = false
for (key,value) in q.enumerated() {
if (value - 1) - key > 2 {
isChaotic = true
break
}
for index in stride(from: max(0, value - 2), to: key, by: 1){
if q[index] > value {
bCount += 1
}
}
}
isChaotic ? print("Too chaotic") : print("\(bCount)")
}
What you basically need to do is to first check if the element in each loop is on it's correct position. And if not you find out how much further is it from the right position if its greater than 2 you print "Too chaotic". Your solution is correct uptil this point. But if the difference is less than or equal to 2 then you need to increment the bribes and swap the indices to represent updated array. Furthermore if there are two swaps then you need to represent how the array would be effected by these 2 swaps and hence swap these values before the next iteration to ensure the array is in the condition it would be after these swaps.
Please refer to my solution below. It passes for all test cases:
func swapValues( arr:inout [Int],index:Int, times: Int, bribes:inout Int) -> Bool {
if times == 0 {
return false
}
if arr[index] > arr[index+1] {
let temp = arr[index+1]
arr[index+1] = arr[index]
arr[index] = temp
bribes = bribes + 1
return swapValues(arr: &arr, index: index+1, times: times-1,bribes: &bribes)
}else{
var diff = abs(arr[index+1] - (index+2))
if diff > 2 {
print("Too chaotic")
return true
}
var tooChaotic = swapValues(arr: &arr, index: index+1, times: diff,bribes:&bribes)
if tooChaotic {
return true
}
return swapValues(arr: &arr, index: index, times: times, bribes: &bribes)
}
}
func minimumBribes(q: [Int]) -> Void {
var qC = q
var bribes = 0
var i = 0
while i <= qC.count-1{
if i+1 == qC[i] {
i = i + 1
continue
}
let diff = abs(qC[i] - (i+1))
if diff > 2 {
print("Too chaotic")
return
}
var tooChaotic = swapValues(arr: &qC, index: i, times: diff, bribes: &bribes)
if tooChaotic {
return
}
}
print(bribes)
}
I found this short and easy solution.
func minimumBribes(q: [Int]) -> Void {
var ans = 0
var shouldShow = true
for i in stride(from: (q.count - 1), through: 0, by: -1) {
if (q[i] - (i+1) > 2) {
shouldShow = false
break;
}
for j in stride(from: max(0, q[i] - 2), to: i, by: 1){
if q[j] > q[i] {
ans += 1
}
}
}
if shouldShow {
print(ans)
} else {
print("Too chaotic")
} }
https://github.com/AnanthaKrish/example-ios-apps

how to take binary string input from user in swift

I want to take input from user in binary, What I want is something like:
10101
11110
Then I need to perform bitwise OR on this. I know how to take input and how to perform bitwise OR, only I want to know is how to convert because what I am currently using is not giving right result. What I tried is as below:
let aBits: Int16 = Int16(a)! //a is String "10101"
let bBits: Int16 = Int16(b)! //b is String "11110"
let combinedbits = aBits | bBits
Edit: I don't need decimal to binary conversion with radix, as my string already have only 0 and 1
String can have upto 500 characters like:
10011011111010110111001011001001101110111110110001001111001111101111010110110111‌​00111001100011111010
this is beyond Int limit, how to handle that in Swift?
Edit2 : As per vacawama 's answer, below code works great:
let maxAB = max(a.count, b.count)
let paddedA = String(repeating: "0", count: maxAB - a.count) + a
let paddedB = String(repeating: "0", count: maxAB - b.count) + b
let Str = String(zip(paddedA, paddedB).map({ $0 == ("0", "0") ? "0" : "1" }))
I can have array of upto 500 string and each string can have upto 500 characters. Then I have to get all possible pair and perform bitwise OR and count maximum number of 1's. Any idea to make above solution more efficient? Thank you
Since you need arbitrarily long binary numbers, do everything with strings.
This function first pads the two inputs to the same length, and then uses zip to pair the digits and map to compute the OR for each pair of characters. The resulting array of characters is converted back into a String with String().
func binaryOR(_ a: String, _ b: String) -> String {
let maxAB = max(a.count, b.count)
let paddedA = String(repeating: "0", count: maxAB - a.count) + a
let paddedB = String(repeating: "0", count: maxAB - b.count) + b
return String(zip(paddedA, paddedB).map({ $0 == ("0", "0") ? "0" : "1" }))
}
print(binaryOR("11", "1100")) // "1111"
print(binaryOR("1000", "0001")) // "1001"
I can have array of upto 500 string and each string can have upto 500
characters. Then I have to get all possible pair and perform bitwise
OR and count maximum number of 1's. Any idea to make above solution
more efficient?
You will have to do 500 * 499 / 2 (which is 124,750 comparisons). It is important to avoid unnecessary and/or repeated work.
I would recommend:
Do an initial pass to loop though your strings to find out the length of the largest one. Then pad all of your strings to this length. I would keep track of the original length of each string in a tiny stuct:
struct BinaryNumber {
var string: String // padded string
var length: Int // original length before padding
}
Modify the binaryOR function to take BinaryNumbers and return Int, the count of "1"s in the OR.
func binaryORcountOnes(_ a: BinaryNumber, _ b: BinaryNumber) -> Int {
let maxAB = max(a.length, b.length)
return zip(a.string.suffix(maxAB), b.string.suffix(maxAB)).reduce(0) { total, pair in return total + (pair == ("0", "0") ? 0 : 1) }
}
Note: The use of suffix helps the efficiency by only checking the digits that matter. If the original strings had length 2 and 3, then only the last 3 digits will be OR-ed even if they're padded to length 500.
Loop and compare all pairs of BinaryNumbers to find largest count of ones:
var numbers: [BinaryNumber] // This array was created in step 1
maxOnes = 0
for i in 0 ..< (numbers.count - 1) {
for j in (i + 1) ..< numbers.count {
let ones = binaryORcountOnes(numbers[i], numbers[j])
if ones > maxOnes {
maxOnes = ones
}
}
}
print("maxOnes = \(maxOnes)")
Additional idea for speedup
OR can't create more ones than were in the original two numbers, and the number of ones can't exceed the maximum length of either of the original two numbers. So, if you count the ones in each number when you are padding them and store that in your struct in a var ones: Int property, you can use that to see if you should even bother calling binaryORcountOnes:
maxOnes = 0
for i in 0 ..< (numbers.count - 1) {
for j in (i + 1) ..< numbers.count {
if maxOnes < min(numbers[i].ones + numbers[j].ones, numbers[i].length, numbers[j].length) {
let ones = binaryORcountOnes(numbers[i], numbers[j])
if ones > maxOnes {
maxOnes = ones
}
}
}
}
By the way, the length of the original string should really just be the minimum length that includes the highest order 1. So if the original string was "00101", then the length should be 3 because that is all you need to store "101".
let number = Int(a, radix: 2)
Radix helps using binary instead of decimical value
You can use radix for converting your string. Once converted, you can do a bitwise OR and then check the nonzeroBitCount to count the number of 1's
let a = Int("10101", radix: 2)!
let b = Int("11110", radix: 2)!
let bitwiseOR = a | b
let nonZero = bitwiseOR.nonzeroBitCount
As I already commented above "10101" is actually a String not a Binary so "10101" | "11110" will not calculate what you actually needed.
So what you need to do is convert both value in decimal then use bitwiseOR and convert the result back to in Binary String (in which format you have the data "11111" not 11111)
let a1 = Int("10101", radix: 2)!
let b1 = Int("11110", radix: 2)!
var result = 21 | 30
print(result)
Output: 31
Now convert it back to binary string
let binaryString = String(result, radix: 2)
print(binaryString)
Output: 11111
--: EDIT :--
I'm going to answer a basic example of how to calculate bitwiseOR as the question is specific for not use inbuilt function as string is very large to be converted into an Int.
Algorithm: 1|0 = 1, 1|1 = 1, 0|0 = 0, 0|1 = 1
So, What we do is to fetch all the characters from String one by one the will perform the | operation and append it to another String.
var str1 = "100101" // 37
var str2 = "10111" // 23
/// Result should be "110111" -> "55"
// #1. Make both string equal
let length1 = str1.characters.count
let length2 = str2.characters.count
if length1 != length2 {
let maxLength = max(length1, length2)
for index in 0..<maxLength {
if str1.characters.count < maxLength {
str1 = "0" + str1
}
if str2.characters.count < maxLength {
str2 = "0" + str2
}
}
}
// #2. Get the index and compare one by one in bitwise OR
// a) 1 - 0 = 1,
// b) 0 - 1 = 1,
// c) 1 - 1 = 1,
// d) 0 - 0 = 0
let length = max(str1.characters.count, str2.characters.count)
var newStr = ""
for index in 0..<length {
let charOf1 = Int(String(str1[str1.index(str1.startIndex, offsetBy: index)]))!
let charOf2 = Int(String(str2[str2.index(str2.startIndex, offsetBy: index)]))!
let orResult = charOf1 | charOf2
newStr.append("\(orResult)")
}
print(newStr)
Output: 110111 // 55
I would like to refer Understanding Bitwise Operators for more detail.
func addBinary(_ a: String, _ b: String) {
var result = ""
let arrA = Array(a)
let arrB = Array(b)
var lengthA = arrA.count - 1
var lengthB = arrB.count - 1
var sum = 0
while lengthA >= 0 || lengthB >= 0 || sum == 1 {
sum += (lengthA >= 0) ? Int(String(arrA[lengthA]))! : 0
sum += (lengthB >= 0) ? Int(String(arrB[lengthB]))! : 0
result = String((sum % 2)) + result
sum /= 2
lengthA -= 1
lengthB -= 1
}
print(result) }
addBinary("11", "1")

why my code is slow when finding Fibonacci sum?

I'm writing answers for project Euler Questions in this repo
but having some performance issues in my solution
Question 2:
Each new term in the Fibonacci sequence is generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
My Solution is
func solution2()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
if (fibonacci(index) % 2 == 0)
{
sum += fibonacci(index)
}
}
print(sum)
}
My Question is, why it gets super slow after iteration 42, i want to do it for 4000000 as the question says, any help?
solution 2
func solution2_fast()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<4000000
{
print (index)
let f = findFibonacciNumber(Double(index))
if (f % 2 == 0)
{
sum += f
}
}
print(sum)
}
The most important thing about PE questions is to think about what it is asking.
This is not asking you to produce all Fibonacci numbers F(n) less than 4000000. It is asking for the sum of all even F(n) less than 4000000.
Think about the sum of all F(n) where F(n) < 10.
1 + 2 + 3 + 5 + 8
I could do this by calculating F(1), then F(2), then F(3), and so on... and then checking they are less than 10 before adding them up.
Or I could store two variables...
F1 = 1
F2 = 2
And a total...
Total = 3
Now I can turn this into a while loop and lose the recursion altogether. In fact, the most complex thing I'm doing is adding two numbers together...
I came up with this...
func sumEvenFibonacci(lessThan limit: Int) -> Int {
// store the first two Fibonacci numbers
var n1 = 1
var n2 = 2
// and a cumulative total
var total = 0
// repeat until you hit the limit
while n2 < limit {
// if the current Fibonacci is even then add to total
if n2 % 2 == 0 {
total += n2
}
// move the stored Fibonacci numbers up by one.
let temp = n2
n2 = n2 + n1
n1 = temp
}
return total
}
It runs in a fraction of a second.
sumEvenFibonacci(lessThan: 4000000)
Finds the correct answer.
In fact this... sumEvenFibonacci(lessThan: 1000000000000000000) runs in about half a second.
The second solution seems to be fast(er) although an Int64 will not be sufficient to store the result. The sum of Fibonacci numbers from 2..91 is 7,527,100,471,027,205,936 but the largest number you can store in an Int64 is 9,223,372,036,854,775,807. For this you need to use some other types like BigInteger
Because you use the recursive, and it cache in the memory.If you iteration 42, it maybe has so many fibonacci function in your memory, and recursive.So it isn't suitable for recursive, and you can store the result in the array, not the reason of the swift.
this is the answer in two different ways
func solution2_recursive()
{
func fibonacci(number: Int) -> (Int)
{
if number <= 1
{
return number
}
else
{
return fibonacci(number - 1) + fibonacci(number - 2)
}
}
var sum = 0
print("calculating...")
for index in 2..<50
{
print (index)
let f = fibonacci(index)
if( f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}
solution 2
func solution2()
{
var phiOne : Double = (1.0 + sqrt(5.0)) / 2.0
var phiTwo : Double = (1.0 - sqrt(5.0)) / 2.0
func findFibonacciNumber (nthNumber : Double) -> Int64
{
let nthNumber : Double = (pow(phiOne, nthNumber) - (pow(phiTwo, nthNumber))) / sqrt(5.0)
return Int64(nthNumber)
}
var sum : Int64 = 0
print("calculating...")
for index in 2..<50
{
let f = findFibonacciNumber(Double(index))
if(f < 4000000)
{
if (f % 2 == 0)
{
sum += f
}
}
else
{
print(sum)
return
}
}
}

Swift convert decimal String to UInt8-Array

I have a very long String (600+ characters) holding a big decimal value (yes I know - sounds like a BigInteger) and need the byte representation of this value.
Is there any easy way to archive this with swift?
static func decimalStringToUInt8Array(decimalString:String) -> [UInt8] {
...
}
Edit: Updated for Swift 5
I wrote you a function to convert your number string. This is written in Swift 5 (originally Swift 1.2).
func decimalStringToUInt8Array(_ decimalString: String) -> [UInt8] {
// Convert input string into array of Int digits
let digits = Array(decimalString).compactMap { Int(String($0)) }
// Nothing to process? Return an empty array.
guard digits.count > 0 else { return [] }
let numdigits = digits.count
// Array to hold the result, in reverse order
var bytes = [UInt8]()
// Convert array of digits into array of Int values each
// representing 6 digits of the original number. Six digits
// was chosen to work on 32-bit and 64-bit systems.
// Compute length of first number. It will be less than 6 if
// there isn't a multiple of 6 digits in the number.
var ints = Array(repeating: 0, count: (numdigits + 5)/6)
var rem = numdigits % 6
if rem == 0 {
rem = 6
}
var index = 0
var accum = 0
for digit in digits {
accum = accum * 10 + digit
rem -= 1
if rem == 0 {
rem = 6
ints[index] = accum
index += 1
accum = 0
}
}
// Repeatedly divide value by 256, accumulating the remainders.
// Repeat until original number is zero
while ints.count > 0 {
var carry = 0
for (index, value) in ints.enumerated() {
var total = carry * 1000000 + value
carry = total % 256
total /= 256
ints[index] = total
}
bytes.append(UInt8(truncatingIfNeeded: carry))
// Remove leading Ints that have become zero.
while ints.count > 0 && ints[0] == 0 {
ints.remove(at: 0)
}
}
// Reverse the array and return it
return bytes.reversed()
}
print(decimalStringToUInt8Array("0")) // prints "[0]"
print(decimalStringToUInt8Array("255")) // prints "[255]"
print(decimalStringToUInt8Array("256")) // prints "[1,0]"
print(decimalStringToUInt8Array("1024")) // prints "[4,0]"
print(decimalStringToUInt8Array("16777216")) // prints "[1,0,0,0]"
Here's the reverse function. You'll notice it is very similar:
func uInt8ArrayToDecimalString(_ uint8array: [UInt8]) -> String {
// Nothing to process? Return an empty string.
guard uint8array.count > 0 else { return "" }
// For efficiency in calculation, combine 3 bytes into one Int.
let numvalues = uint8array.count
var ints = Array(repeating: 0, count: (numvalues + 2)/3)
var rem = numvalues % 3
if rem == 0 {
rem = 3
}
var index = 0
var accum = 0
for value in uint8array {
accum = accum * 256 + Int(value)
rem -= 1
if rem == 0 {
rem = 3
ints[index] = accum
index += 1
accum = 0
}
}
// Array to hold the result, in reverse order
var digits = [Int]()
// Repeatedly divide value by 10, accumulating the remainders.
// Repeat until original number is zero
while ints.count > 0 {
var carry = 0
for (index, value) in ints.enumerated() {
var total = carry * 256 * 256 * 256 + value
carry = total % 10
total /= 10
ints[index] = total
}
digits.append(carry)
// Remove leading Ints that have become zero.
while ints.count > 0 && ints[0] == 0 {
ints.remove(at: 0)
}
}
// Reverse the digits array, convert them to String, and join them
return digits.reversed().map(String.init).joined()
}
Doing a round trip test to make sure we get back to where we started:
let a = "1234567890987654321333555777999888666444222000111"
let b = decimalStringToUInt8Array(a)
let c = uInt8ArrayToDecimalString(b)
if a == c {
print("success")
} else {
print("failure")
}
success
Check that eight 255 bytes is the same as UInt64.max:
print(uInt8ArrayToDecimalString([255, 255, 255, 255, 255, 255, 255, 255]))
print(UInt64.max)
18446744073709551615
18446744073709551615
You can use the NSData(int: Int, size: Int) method to get an Int to NSData, and then get the bytes from NSData to an array: [UInt8].
Once you know that, the only thing is to know the size of your array. Darwin comes in handy there with the powfunction. Here is a working example:
func stringToUInt8(string: String) -> [UInt8] {
if let int = string.toInt() {
let power: Float = 1.0 / 16
let size = Int(floor(powf(Float(int), power)) + 1)
let data = NSData(bytes: &int, length: size)
var b = [UInt8](count: size, repeatedValue: 0)
return data.getBytes(&b, length: size)
}
}
You can always do:
let bytes = [UInt8](decimalString.utf8)
If you want the UTF-8 bytes.
Provided you had division implemented on your decimal string you could divide by 256 repeatedly. The reminder of the first division is the your least significant byte.
Here's an example of division by a scalar in C (assumed the length of the number is stored in A[0] and writes the result in the same array):
void div(int A[], int B)
{
int i, t = 0;
for (i = A[0]; i > 0; i--, t %= B)
A[i] = (t = t * 10 + A[i]) / B;
for (; A[0] > 1 && !A[A[0]]; A[0]--);
}

Resources