I am trying to update the value of Int variables (that are from one function) inside of another function. What I have right now is two variables that are declared 0 outside of any functions. Then in one function, they are assigned a value of either 1 or 0. Up until this point everything is fine. Then I am trying to update the variables when the user taps a UIImageView (subtracting 3 from one variable and adding two to the other). The problem I am having is that instead of subtracting 3 and adding 2 to the 1 and 0, it is subtracting 3 and adding 2 to the original 0 that the variables were declared as.
var playerA:Int = 0
var playerB:Int = 0
func firstFunction(playerA:Int, playerB:Int) {
if counter%2 {
playerA = 1
playerB = 0
}
else {
playerA = 0
playerB = 1
}
}
func secondFunction(playerA:Int, playerB:Int) {
counter += 1
if counter%2 0 {
playerA += -3
playerB += 2
}
else {
playerA += 2
playerB += =3
}
Here secondFunction returns -3 and 2 instead of -2 and 2.
My idea to fix this is to use an array that is returned from firstFunction, and to refer to the elements by index (like this ->[Int, Int] where the Ints are playerA and playerB).
I'm going to assume there are some typo's in your code portion, so I've decided to fix them up so the functions are reflective of your write up. There's also no reason to pass in the arguments in this case:
var counter: Int = 0
var playerA: Int = 0
var playerB: Int = 0
func firstFunction() {
if counter % 2 == 0 {
playerA = 1
playerB = 0
}
else
{
playerA = 0
playerB = 1
}
}
func secondFunction() {
counter += 1
if counter % 2 == 0 {
playerA -= 3
playerB += 2
}
else
{
playerA += 2
playerB -= 3
}
}
You should show us how you call your functions, but it is not going to work unless you declare the parameters as inout. Read up here to understand how it works (scroll down to In-Out Parameters), it comes with this example:
func swapTwoInts(inout a: Int, inout _ b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"
Related
I have a problem with a while-loop in kotlin.
The task i have to solve is to encode a binary-string in to a pseudo-string.
I've written a function that is supposed to receive and encode the binary string like "1000011" (7-bit) into "0 0 00 0000 0 00" in this case.
fun doEncode (input : String) : String {
var input = input
var result : MutableList<String> = mutableListOf()
var mOneActive = 0
var mNullActive = 0
var mNullCount = 0
var mOneCount = 0
var mIndexInput = 0
var mRangeInput = input.length-1
for (range in 0 until mRangeInput) {
while (input[mIndexInput] == '0' && mIndexInput < mRangeInput) {
mNullActive = 1
mNullCount += 1
mIndexInput += 1
}
if (mNullActive == 1) {
result.add("00")
result.add(" ")
for(range in 0 until mNullCount) {
result.add("0")
}
result.add(" ")
mNullActive = 0
mNullCount = 0
}
while (input[mIndexInput] == '1' && mIndexInput < mRangeInput) {
mOneActive = 1
mOneCount += 1
mIndexInput += 1
}
if (mOneActive == 1) {
result.add("0")
result.add(" ")
for(range in 0 until mOneCount) {
result.add("0")
}
result.add(" ")
mOneActive = 0
mOneCount = 0
}
}
var output = result.reduce { i, value -> i + value }
return output
}
But the function only encode the first 6 bit of the binary-string. The last on is missing.
I don´t see the mistake. When i increase the range (var mRangeInput) i get a "outofboundsexeption".
I have no further idea, so any help is welcome.
Look at these two lines.
var mRangeInput = input.length-1
for (range in 0 until mRangeInput) {
mRangeInput is the input length minus one. And until creates a range with an exclusive end. You have to choose one way or the other to exclude the final value of the range from 0 to the size, but you've done it both ways, so you've excluded one too many.
I didn't check anything else in your code. I don't know what the encoding is supposed to be.
I am trying to get all possible combinations of a char*. This string consits of four values: two numbers and two different letters. For example:
char *text = "01ab";
There should be
so
different combinations for my example string, which seems to be true (done by hand):
Combinations for values: 0, 1, a, b:
0 0 a b 1 1 a b a 0 0 b b 0 0 a
0 0 b a 1 1 b a a 0 1 b b 0 1 a
0 1 a b 1 0 a b a 0 b 0 b 0 a 0
0 1 b a 1 0 b a a 0 b 1 b 0 a 1
0 a 0 b 1 a 1 b a 1 b 0 b 1 0 a
0 a 1 b 1 a 0 b a 1 b 1 b 1 1 a
0 a b 0 1 a b 1 a 1 0 b b 1 a 0
0 a b 1 1 a b 0 a 1 1 b b 1 a 1
0 b 0 a 1 b 1 a a b 0 0 b a 0 0
0 b 1 a 1 b 0 a a b 0 1 b a 0 1
0 b a 0 1 b a 1 a b 1 0 b a 1 0
0 b a 1 1 b a 0 a b 0 0 b a 1 1
My approach would be the same as the one I did by hand:
get all combinations with the first index of text at the start, then all combinations of the second index of text and so on. So something like this:
void printPasswordCombinations()
{
char *all_values = "01ab";
int len = strlen(all_values);
char *tmp_pwd = malloc(sizeof(len) * sizeof(char));
for(int i=0 ; i<len ; i++)
{
tmp_pwd[0] = all_values[i];
/* len-1, since the first index is already set. */
for(int j=0 ; j<len-1 ; j++)
{
}
}
printf("%s\n", tmp_pwd);
free(tmp_pwd);
}
Now I am a bit confused about how to continue after the first index of the combination. There are several examples for all combinations, but my problem seems to be a bit different, since my the numbers in the combination could be the same and only the letters have to be different.
How could I achieve to print all combinations to my console?
I implemented a function which calculates the amount of possible combinations, so just assume this is already done.
It would be nice if the algorithm would work for any amounts of numbers and letters, so for example all combinations of a text of lenght 6 with four different numbers and two different letters could also be calculated.
The language doesn't matter, any advice is appreciated.
Your problem can be solved by backtracking strategy. It will create all
possible combinations.
I know you want to remove duplicate combinations in case the two number are the same, to get rid of them, you can use a hash table to store generated combination, and then, each time you generate a new combination, bring it to the hash table to check if it was generated or not(if not, enter it to the hash table and print it out, ignore printing in vice versa). There for my pseudocode as follow (you can have a better way):
val characters = [/*4 characters*/]
val picked = [false,false,false,false]
val hashtable = empty
function genetate(string aCombin):
if aCombin.size == 4:
if(hashtable.contains(aCombin)):
//do nothing
else:
print(aCombin)
hashtable.add(aCombin)
for i in characters.size:
if(picked[i]==false):
picked[i]=true
aCombin.add(characters[i])
generate(aCombin)
picked[i]=false //backtrack
aCombine.popBack() //remove the last character
I used Javascript because it can run in browser and language doesn't matter. The below method uses recursion. Try it with '0123ab'.
'use strict';
const input = '01ab';
const reLetters = /[^0-9]/g;
const reDigits = /[0-9]/g;
const nLetters = input.replace(reDigits, '').length;
const nDigits = input.replace(reLetters, '').length;
const findComb = cur => {
if (cur.length === input.length)
return console.log(cur);
for (let l of input) {
if (l.match(reDigits)) {
if (cur.replace(reLetters, '').length === nDigits) continue;
} else {
if (cur.match(l) || cur.replace(reDigits, '').length === nLetters) continue;
}
findComb(cur + l);
}
}
findComb('');
Here is a version without "removing letters to count digits". it is about 20% more efficient. I used nodejs and '01234abc' as input to measure.
'use strict';
const input = '01ab';
const reLetters = /[^0-9]/g;
const reDigits = /[0-9]/g;
const maxLetters = input.replace(reDigits, '').length;
const maxDigits = input.replace(reLetters, '').length;
const findComb = (cur = '', nDigits = 0, nLetters = 0) => {
if (cur.length === input.length)
return console.log(cur);
for (let l of input) {
if (l.match(reDigits)) {
if (nDigits < maxDigits)
findComb(cur + l, nDigits + 1, nLetters);
} else {
if (cur.match(l)) continue;
if (nLetters < maxLetters)
findComb(cur + l, nDigits, nLetters + 1);
}
}
}
findComb();
Here it is without recursion. This is slowest of all, but can be improved.
'use strict';
const input = '01ab';
const reLetters = /[^0-9]/g;
const reDigits = /[0-9]/g;
const nLetters = input.replace(reDigits, '').length;
const nDigits = input.replace(reLetters, '').length;
let cur = '', l = undefined;
do {
l = input[input.indexOf(l) + 1];
if (l !== undefined) {
if (l.match(reDigits)) {
if (cur.replace(reLetters, '').length === nDigits) continue;
} else {
if (cur.match(l) ||
cur.replace(reDigits, '').length === nLetters) continue;
}
if (cur.length + 1 === input.length) {
console.log(cur + l);
} else {
cur = cur + l;
l = undefined;
}
} else {
l = cur[cur.length - 1];
cur = cur.slice(0, -1);
}
} while (cur != '' || l != undefined);
A recursive approach would be the easy way here.
Let's consider that you want to generate all strings with m letters, all of them distinct, taken from a letters[m] array, and n numbers, that can be repeated, taken from a numbers[N] array (n can be smaller, of same size of bigger than N, it does not really matter).
You can solve it this way then (pseudo code, C style):
void print_them_all(char *numbers, int nb_numbers_in_result, int n \
char *letters, bool *is_letter_used, int nb_letters_in_result, int m,
char *current_string){
if ((nb_numbers_in_result == n) && (nb_letters_in_result == m)){
// terminal case -> time to print the current string
printf("%s\n", current_string);
} else {
// string not completely built yet
// get the index where the next char will be added
current_index = nb_letters_in_result + nb_numbers_in_result;
if (nb_numbers_in_result < n){ // still possible to add a number
for (int i = 0; i < N; i++){
current_string[current_index] = numbers[i];
print_them_all(numbers, nb_numbers_in_result+1, n, \
letters, is_letter_used, nb_letters_in_result, m, \
current_string);
}
}
if (nb_letters_in_result < m){ // still possible to add a letter
for (int i = 0; i < m; i++) {
if (is_letter_used[i] == false){ // check the letter has not been added yet
// keep track that the letter has been added by 'marking' it
is_letter_used[i] = true;
// add it
current_string[i] = letters[i];
// recursive call
print_them_all(numbers, nb_numbers_in_result, n, \
letters, is_letter_used, nb_letters_in_result+1, m, \
current_string);
// now 'unmark' the letter
is_letter_used[i] = false;
}
}
}
}
}
To solve this kind of problem, the recursive approach is necessary. It works as follows:
if I have a string with k numbers in it already, k<n, then I can add any number to it, and I can continue (now my string will have k+1 numbers in it).
If I have a string with k letters in it already, k<m, then I can add any letter that was not added already (the array of booleans helps to make sure it is the case), and I can continue.
If my string is ready for print, print it.
The first call should be done with the boolean array initialized to false everywhere, and 0 for the values of nb_letters_in_result and nb_numbers_in_result, since you have not added any number or letter in your result string yet.
As for your result string, since you code in C, don't forget to allocate memory for it:
char *current_string = malloc((m+n+1) * sizeof(char));
and to null-terminate it:
current_string[m+n] = '\0';
I also found an interesting solution for my question.
Assume my example string 01ab.
First we want to create all combinations of the numbers 01 and the permutation of ab.
There are plenty examples of how to solves this.
So now we have all combinations of 01 and ab. I will call them producer combinations:
10 ab
01 ba
11
00
Now we want to combine all numbers with all letters but with the rule
The order of the numbers or letters must not be reserved for each combination
So if we combine 10 with ab we get:
10ab
1a0b
a10b
now we move b to the left side until it is about to swap its place with a, which is forbidden because of my rule. We do this for every combination:
10ab produces:
10ab
since b is already next to a.
1a0b produces:
1ab0
so we got one more combination.
a10b produces:
a1b0
ab10
so we got 2 more combinations.
Now we have all possible combinations for 01 and ab:
10ab
1a0b
a10b
1ab0
a1b0
ab10
Since our producer combinations contain 8 elements we have to do this step 8 times with all elements. The resulting combinations will always contain 6 elements like in my example which leads us to 48 elements in total as I calculated in my question.
I wonder why my solution to this LeetCode "Move Zeros" problem is slower than the majority of other submissions. Is there a better way to approach this problem to make it faster?
The question is as follows:
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. You must do this in-place without making a copy of the array.
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
This is my solution:
func moveZeroes(_ nums: inout [Int]) {
var index = 0
for (i,n) in nums.enumerated()
{
if n != 0
{
nums[index] = n
index += 1
}
}
while index < nums.count
{
nums[index] = 0
index += 1
}
}
LeetCode gives me these statistics:
Runtime: 52 ms, faster than 40.50% of Swift online submissions for Move Zeroes.
Memory Usage: 19.4 MB, less than 13.33% of Swift online submissions for Move Zeroes.
EDIT 1:
If I approach the problem as follows, it does not move the zeros at the end,
EDIT 2:
Here is 36ms in-place solution for you :
class Solution {
func moveZeroes(_ nums: inout [Int]) {
if nums.count < 2 {
return
}
var j = 0
while j < nums.count, nums[j] != 0 {
j += 1
}
if j < nums.count - 1 {
for i in j+1..<nums.count {
if nums[i] != 0 {
nums.swapAt(i, j)
j += 1
}
}
}
}
}
From what I can see, it's likely other submissions are doing this
Check and count 0's in string
Remove 0's
Replace number of 0's at the end of the string
A logical method no doubt, but I'd say yours just picks the basic needs of the challenge and goes for it.
I would personally use:
input = input.filter { $0 != 0 } + input.filter { $0 == 0 }
which can be simplified to one pass:
let nonZeros = input.filter { $0 != 0 }
input = nonZeros + Array(repeating: 0, count: input.count - nonZeros.count)
EDIT: The simplest version without creating a new array would be some primitive version of bubble sort, e.g.:
var numZeros = 0
// iterate array from start to end
for (offset, element) in input.enumerated() {
if element == 0 {
// count every zero
numZeros += 1
} else if numZeros > 0 {
// move every non-zero element left
input[offset - numZeros] = element
// replace with zero
input[offset] = 0
}
}
Another approach is the half-stable-partition algorithm. The benefit is the items are swapped rather than removed and inserted/appended.
Half-stable means the order of the left side of the split point is preserved.
extension Array {
mutating func halfStablePartition(indexes : IndexSet) { // code is O(n)
guard var i = indexes.first, i < count else { return }
var j = index(after: i)
var k = indexes.integerGreaterThan(i) ?? endIndex
while j != endIndex {
if k != j { swapAt(i, j); formIndex(after: &i) }
else { k = indexes.integerGreaterThan(k) ?? endIndex }
formIndex(after: &j)
}
}
}
var input = [0,1,0,3,12]
let indices = IndexSet(input.indices.filter{input[$0] == 0})
input.halfStablePartition(indexes: indices)
Swift 4.2 or later using removeAll mutating method:
Mutating the input:
class Solution {
func moveZeroes(_ nums: inout [Int]) {
var counter = 0
nums.removeAll {
if $0 == 0 {
counter += 1
return true
}
return false
}
nums += repeatElement(0, count: counter)
}
}
A similar approach for Swift 4.1 or earlier
func moveZeroes(_ nums: inout [Int]) {
var counter = 0
nums.indices.reversed().forEach {
if nums[$0] == 0 {
counter += 1
nums.remove(at: $0)
}
}
nums += repeatElement(0, count: counter)
}
var input = [0,1,0,3,12]
moveZeroes(&input)
input // [1, 3, 12, 0, 0]
Non mutating approach:
func moveZeroes(_ nums: [Int]) -> [Int] {
var counter = 0
return nums.filter {
if $0 == 0 { counter += 1 }
return $0 != 0
} + repeatElement(0, count: counter)
}
let input = [0,1,0,3,12]
let zerosMoved = moveZeroes(input)
zerosMoved // [1, 3, 12, 0, 0]
For modifying array in place, and keeping it:
O(n) for Time Complexity
O(1) for Space Complexity
Cracked my head way to long for this one. The cleanest way if you swap element that is NOT zero:
func moveZeroes(_ nums: inout [Int]) {
// amount of swaps, will be used a as reference for next swap index
var j = 0
for (i, e) in nums.enumerated() {
if e != 0 {
nums.swapAt(j, i)
j += 1
}
}
}
One fast solution is to shift non-zero elements to the left by the amount of zeros encountered until then:
func moveZeroes(_ nums: inout [Int]) {
var offset = 0
for i in 0..<nums.count {
if nums[i] == 0 { offset += 1 }
else { nums.swapAt(i, i-offset) }
}
}
This solution takes exactly N steps, and at each step we either perform an addition, or a swap, which are both quite fast.
Your solution, on the other hand required two iterations, resulting in 2*N steps, which is why it was slower than other solutions.
I'm trying to implement something like binary masking where I turn an Int into an array of it's components (powers of 2), for example:
69 = [64, 4, 1]
I don't want to use binary masking and shifting, because I want to use Swift enums for interface elements:
enum State: Int{
case readyButton = 1
case workingButton = 2
case sleepingButton = 4
//etc
}
then 7 = [.sleepingButton, .workingButton, .readyButton] // 7 = 4+2+1
Are there some tools built in Swift to help me turn an Int into power of 2 components?
You may be looking for something like this. As it is written, it will crash when the values do not match up, but you can adapt it for your purposes. Though it does use shifting, it still converts to your enum nicely.
extension UInt32 {
func state() -> [State] {
var bitvals: [UInt32] = []
var mask: UInt32 = 1
while mask > 0 {
if mask & self > 0 {
bitvals.append(mask)
}
mask = mask << 1
}
let state = bitvals.map { State(rawValue: $0)! }
return state
}
}
enum State: UInt32 {
case readyButton = 1
case workingButton = 2
case sleepingButton = 4
}
let val: UInt32 = 7
print(val.state())
This would print out the example you gave at the end of your question.
Updated answer to convert any Int into an array of powers of 2. Uncomment fatal error if you want it to crash on negative values
enum State: Int {
case illegal = -1
case readyButton = 1
case workingButton = 2
case sleepingButton = 4
}
Here is a general solution for decomposing integers into powers of 2:
extension Int {
func toPowersOf2() -> [Int] {
guard self > 0 else {
// fatalError("The number should be strictly positive")
print("The number should be strictly positive")
return [-1] //not really - use fatal error above to enforce crash if you don't want this behavior
}
var arrayOfPowers: [Int] = [] //Will hold the desired powers
var remainder: Int = self //We will substract found powers from the original number
//Since Ints are coded on 64 bits (the 64th is for the sign)
//Let's create an array of all the powers of 2 that
//could be used to decompose an integer
let powers = (0...62).map { NSDecimalNumber(decimal: pow(2.0, $0)).intValue }
//Let's go from the highest to the lowest power
for i in (0 ..< powers.count).reversed() {
//Here we are looking for the power just smaller than the remainder
if i < powers.count - 1, powers[i] <= remainder, powers[i + 1] > remainder {
let p = powers[i]
arrayOfPowers.append(p)
remainder -= p
}
//if this is the biggest power and it is smaller than the number, then add it to arrayOfPowers
else if i == powers.count - 1, powers[i] <= remainder {
let p = powers[i]
arrayOfPowers.append(p)
}
}
return arrayOfPowers
}
func toStateArray() -> [State] {
let array = self.toPowersOf2().map{ State(rawValue: $0) }.filter{ $0 != nil }
return array as! [State]
}
}
And you could use it like so:
(-1).toStateArray()//[illegal]
0.toStateArray() //[illegal]
7.toPowersOf2() //[4, 2, 1]
7.toStateArray() //[sleepingButton, workingButton, readyButton]
What is the problem with the following function to receive and execute:
func FibFast(num: Int) -> Array<Int> {
var fib_arr = [Int](num)
if num < 1 {
fib_arr[0] = 0
return fib_arr
} else if num < 2 {
fib_arr[1] = 1
return fib_arr
}else {
for var i = 2; i < num; i++ {
fib_arr[i] = fib_arr[i-1] + fib_arr[i-2]
}
return fib_arr
}
}
when I am trying to receive the array like:
var newArray = FibFast(10)
it's producing a bad execution.
You are attempting to subscript the array with indexes that don't exist, similarly in your else case you are trying to subscript to an index of 2 when the array is empty.
the line var fib_arr = [Int]() creates an empty array on integers. when you use fib_arr[0] = 0 you are trying to assign the value at index 0 to have a value of 0 but no value currently exists. I would recommend using the append(_) method ie. fib_arr.append(0).
Also when you pass in a value of 10 or anything that is 2 or more as the num parameter your if-else if-else statement is executing the for loop where you are attempting to access the index of 0 and 1 which have not been set as the earlier statements were never executed as they were skipped by the if-else if-else block.
The for loop and assign the values with subscripts is very indicative of the fact that you've probably learnt a different language before swift. You should note that the classic c-style for loop you are trying to use will be removed from swift soon so its better to get in the habbit of no using it. Ive rewritten your code as close to the way you wrote yours, please don't hesitate to ask if you have any questions about it.
func fib(num: Int) -> [Int] {
var fib_arr = [Int]()
if num == 0 {
fib_arr.append(0)
} else if num == 1 {
fib_arr.append(0)
fib_arr.append(1)
} else {
fib_arr = [0, 1]
for i in 2..<num {
fib_arr.append(fib_arr[i - 1] + fib_arr[i - 2])
}
}
return fib_arr
}
The answer proposed by Blake Lockley can also be coded like this:
func FibFast(num: Int) -> Array<Int> {
var fib_arr = [Int]() // empty array
if num < 1 {
fib_arr += [0] // add element [0]
return fib_arr
} else if num < 2 {
fib_arr += [0] // add element [0]
fib_arr += [1] // add element [1]
return fib_arr
}else {
fib_arr = [0, 1] // init with [0, 1]
for var i = 2; i < num; i++ {
// add computed element
fib_arr += [fib_arr[i-1] + fib_arr[i-2]]
}
return fib_arr
}
}