Why is the number repeating? - arrays

My ultimate goal is to get an array of Ints extracted from a String inputted in a textfield. For this I created a function whose parameter is a String. I use a for-loop to get all the characters from the textfield into an array. Then I loop through the array and append only the numbers (if they're <= 24) to a new array. When I print the array with just numbers, I get the first element of array1 repeating. Why is this happening?
var array1 = [String]()
var array2 = [Int]()
func getDigits (userInput: String) {
for element in userInput {
array1.append(String(element))
}
var mx = 0
var fx = 1
func findNumbers() {
for number in 1...24 {
if array1[mx] == "\(fx)" {
array2.append(Int(String(array1[mx]))!)
} else {
fx += 1
findNumbers()
}
}
}
findNumbers()
print (array2)
}
getDigits(userInput: "4-5")
Output: [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]

This will support multi-digit numbers in your input string, and also filter out-of-range values.
import Foundation
func parseNumbers (userInput: String, splitBy: String, min: Int, max: Int) -> Array<Int> {
let separators = CharacterSet(charactersIn: splitBy)
let numericStrings = userInput.components(separatedBy: separators)
var numArray = [Int]()
for item in numericStrings {
if let number = Int(item) {
if (number >= min) && (number <= max) {
numArray.append(number)
}
}
}
return numArray
}
print(parseNumbers(userInput: "5:hello,34-7 12;103,abc", splitBy: " -:,;", min:1, max:24))
output: [5, 7, 12]

try this
func getDigits (userInput: String) {
let splitsCharacters = ",;:- "
let seperators = CharacterSet(charactersIn: splitsCharacters)
let updateInput = userInput.components(separatedBy: seperators)
print(array1)
func findNumbers() {
for item in updateInput {
if let number = Int(item) {
if number <= 24{
array2.append(number)
}
}
}
}
findNumbers()
print (array2)
}
getDigits(userInput: "4-5 hello, 34;12,23")
Output : [4, 5,12,23]

I am not sure what you are trying to do but you can try something like
Swift 4
func getDigits (userInput: String) {
var resultArray = [Int]()
for char in userInput {
if let number = Int("\(char)"), number < 24 {
resultArray.append(number)
}
}
print(resultArray)
}
testing
getDigits(userInput: "4-5")
//prints => [4, 5]
You need just 1 array to hold the numbers
Note: in swift for the string is array type so you can loop on it directly, but for earlier versions you can use:
for char in userInput.characters {
}
to get the array of string characters

Related

The truth value of array is ambigous

I have gotten this error a few times in my code and I've never come across it before. Sudoku is a 2d numpy array. Can anyone tell me why and how to fix it?
An example of the sudoku array would be
sudoku = np.array([[0, 2, 4, 7, 6, 3, 5, 9, 1], [3, 9, 7, 4, 5, 0, 8, 2, 6], [8, 5, 6, 9, 2, 0, 0, 4, 7], [0, 8, 9, 5, 3, 6, 7, 1, 4], [7, 3, 1, 2, 9, 4, 6, 5, 8], [6, 4, 5, 8, 1, 7, 9, 3, 2], [4, 7, 2, 3, 8, 9, 1, 6, 5], [9, 1, 8, 6, 4, 5, 2, 7, 3], [5, 6, 3, 1, 7, 2, 4, 8, 9]])
import numpy as np
import copy
global subgrids
sudoku = np.array([[0, 2, 4, 7, 6, 3, 5, 9, 1], [3, 9, 7, 4, 5, 0, 8, 2, 6], [8, 5, 6, 9, 2, 0, 0, 4, 7], [0, 8, 9, 5, 3, 6, 7, 1, 4], [7, 3, 1, 2, 9, 4, 6, 5, 8], [6, 4, 5, 8, 1, 7, 9, 3, 2], [4, 7, 2, 3, 8, 9, 1, 6, 5], [9, 1, 8, 6, 4, 5, 2, 7, 3], [5, 6, 3, 1, 7, 2, 4, 8, 9]])
ad = sudoku.tolist()
frontier = sudoku
subgrids = []
moves = [1,2,3,4,5,6,7,8,9]
columns = []
for i in range(0,9):
columns.append([row[i] for row in sudoku])
def is_possible(sudoku):
for i in range(0, 9):
for j in range(1, 10):
if np.any([ad[i].count(j) > 1] or [columns[i].count(j) > 1]):
return False
return True
sc = copy.deepcopy(ad)
for i in range(0,9,3):
for j in range(0,9,3):
subgrids.append(sc[i][j:j+3]+sc[i+1][j:j+3]+sc[i+2][j:j+3])
def get_next_zero(sudoku):
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
index = [i,j] #i is row index, j is column index
possible_values(index,subgrids)
return True
def is_solution(sudoku):
if is_possible(sudoku) == False:
return False
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
return False
return True
def possible_values(ind,grid):
possible_num = []
row = [a for a in sudoku[ind[0]]]
row = list(row)
column = []
for i in range(0,9):
column.append(sudoku[i][ind[1]])
column = list(column)
if ind[0] < 3:
if ind[1] < 3:
sub = grid[0]
elif 2 < ind[1] < 6:
sub = grid[1]
else:
sub = grid[2]
if 2 < ind[0] < 6:
if ind[1] < 3:
sub = grid[3]
elif 2 < ind[1] < 6:
sub = grid[4]
else:
sub = grid[5]
if ind[0] > 5:
if ind[1] < 3:
sub = grid[6]
elif 2 < ind[1] < 6:
sub = grid[7]
else:
sub = grid[8]
sub = list(sub)
for num in moves:
if num not in row and num not in column and num not in sub:
possible_num.append(num)
solver(possible_num, ind)
def solver(actions, where):
if len(actions) < 1:
np.delete(frontier,len(frontier)-1)
else:
for action in actions:
sudoku[where[0]][where[1]] = action
new_state = sudoku
if is_possible(new_state) == True:
np.append(frontier,new_state)
else:
np.delete(frontier,sudoku)
new_state = frontier.pop()
sudoku_solver(new_state)
def sudoku_solver(sudoku):
if is_possible(sudoku) == False:
print (np.full((9,9),-1))
elif is_solution(sudoku) == True:
print(sudoku)
else:
get_next_zero(sudoku)
sudoku_solver(sudoku)
for num in moves:
if num not in row and num not in column and num not in sub:
possible_num.append(num)
solver(possible_num, ind)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Another point in the code too
def is_solution(sudoku):
if is_possible(sudoku) == False:
return False
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
return False
return True
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

How to get depth of tree of arrays given total num items and max array size?

Given this divide algorithm and sample data:
const data = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0
]
function divide(data, size) {
const result = []
for (let i = 0; i < data.length; i += size) {
const chunk = data.slice(i, i + size);
result.push(chunk)
}
if (result.length > size) {
return divide(result, size)
}
return result;
}
const result = divide(data, 5);
console.log(result)
How do you calculate the number of levels in the resulting tree? In this case of block size 5, I think there are 3 are 4 levels about, but what is the equation to use so you don't have to compute the actual tree? Basically getDepth(numItems, blockSize)?
Every recursive call reduces the input size by a factor of blocksize.
Starting with your example of 100 items. This is grouped into 20, these 20 are grouped into 4 and the algorithm ends.
The expression that capture this is log with a base of blocksize.
f(n,m) = ceil(log_base_m(n))
The depth of the example tree is
        ceil(log5(99))
In general:
        ceil(logchunksize(datasize-1))

.sort() acting weird with multiple arrays of text and numbers

I have been messing around with the .sort() and .concat() functions trying to combine multiple arrays of numbers and text into one and chronologically order it. It seems to work fine if only numbers are input into the array but as soon as there is text it seems to place it randomly, in this case between 6 and 7. Also, if I remove the number 3 from the array, the number 4 ends up out of order after the text, both being between 9 and 10. I have no idea why it is doing this if anyone could help.
With only numbers:
var multiArray = [[2, 8, 1, 7, 9], [6, 3, 5, 4, 10]];
// returns 1,10,2,3,4,5,6,7,8,9
document.write(multiArray[0]
.concat(multiArray[1])
.sort()
+"<br/>");
// returns 1,2,3,4,5,6,7,8,9,10
document.write(multiArray[0]
.concat(multiArray[1])
.sort((a,b)=>a-b)
+"<br/>");
and with text
var multiArray = [[2, 8, 1, 7, 9], [6, 3, 5, "text", 4, 10]];
// returns 1,2,3,4,5,6,text,7,8,9,10
document.write(multiArray[0]
.concat(multiArray[1])
.sort((a,b)=>a-b)
+"<br/>");
and without 3
var multiArray = [[2, 8, 1, 7, 9], [6, 5, "text", 4, 10]];
// returns 1,2,5,6,7,8,9,text,4,10
document.write(multiArray[0]
.concat(multiArray[1])
.sort((a,b)=>a-b)
+"<br/>");
first, combine all arrays in a single array
var multiArray = [[2, 8, 1, 'foo', 7, '1', 9], [6, 5, 'text', 4, 'bar', 10]];
var flattenArray = [].concat(...multiArray); // [ 2, 8, 1, 'foo', 7, '1', 9, 6, 5, 'text', 4, 'bar', 10 ]
then sort separately numbers and strings
const sortedNumbers = flattenArray
.filter(n => typeof n === 'number')
.sort((a, b) => a - b);
const sortedStrings = flattenArray
.filter(n => typeof n === 'string')
.sort();
finally, concat both
const sorted = sortedNumbers.concat(sortedStrings); // [ 1, 2, 4, 5, 6, 7, 8, 9, 10, '1', 'bar', 'foo', 'text' ]
I assume you want strings after your numbers. Otherwise, simply invert the concatenation:
const sorted = sortedStrings.concat(sortedNumbers);

Swift Joining 2 Arrays in Specific Order

I wrote the following code in a playground and it works fine, but it seems a little messy. Is there a more concise way of writing this in Swift?
I want a string to look like the following:
1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14
I will not know how many values in each array and the arrays may not be even multiples, but I will know the relationship of 3 array1 values for each array2 value
let array1 = [1,2,3,4,5,6,7,8] //sample 1st array
let array2 = [12,13,14] //sample 2nd array
let relationshipInterval = 3
let remainder = (array1.count % relationshipInterval)
let multiples = (array1.count - remainder)/relationshipInterval
var string = ""
var array1Start = 0
var array1End = relationshipInterval-1
var array2Value = 0
for _ in 1...multiples {
for array1value in array1[array1Start...array1End] {
string += "\(array1value), "
string += String(array2[array2Value])+", "
}
array1Start = array1End + 1
array1End = array1Start + relationshipInterval - 1
array2Value += 1
}
for array1value in array1[array1Start...array1Start+remainder-1] {
string += "\(array1value), "
string += String(array2[array2Value])+", "
}
print (string) //prints 1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14
I'm not sure if this covers all of the use cases, but using zip, flatMap, and joined you do this in a single step!
let array1 = [1,2,3,4,5,6,7,8]
let array2 = [12, 13, 14]
let text = zip(array1, array2.flatMap({ [$0, $0, $0] }))
.flatMap({ [$0, $1] })
.map({ String($0) })
.joined(separator: ", ")
// text -> "1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14"
Here's that one-liner broken into four steps so it's clearer what's happening at each stage:
// 1. create an array with each element in array2 is trippled:
let trippled = array2.flatMap({ item in
return [item, item, item]
})
// trippled -> [12, 12, 12, 13, 13, 13, 14, 14, 14]
// 2. zip array1 with the trippled array:
let zipped = zip(array1, trippled)
// zipped -> Zip2Sequence(_sequence1: [1, 2, 3, 4, 5, 6, 7, 8], _sequence2: [12, 12, 12, 13, 13, 13, 14, 14, 14])
// 3. flatten the zipped aray
let combined = zipped.flatMap({ leftItem, rightItem in
return [leftItem, rightItem]
})
// combined -> [1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14]
// 4. tranform to a string
let text = combined.map({ item in
return "\(item)"
}).joined(separator: ", ")
// text -> "1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14"

Merge arrays inside of arrays

I have this array:
a = [[1,2,3,4,5],[3,5,6,8,12,45],[3,2,1,5,7,9,10,11],[3,5,6,8,2,1,3,4,6]]
I want to merge its inner arrays so that they become:
a = [[1,2,3,4,5,3,5,6,8,12,45],[3,2,1,5,7,9,10,11,3,5,6,8,2,1,3,4,6]]
How can I do this?
You need to do
a = [
[1, 2, 3, 4, 5],
[3, 5, 6, 8, 12, 45],
[3, 2, 1, 5, 7, 9, 10, 11],
[3, 5, 6, 8, 2, 1, 3, 4, 6]
]
a.each_slice(2).map(&:flatten)
# => [
# [1, 2, 3, 4, 5, 3, 5, 6, 8, 12, 45],
# [3, 2, 1, 5, 7, 9, 10, 11, 3, 5, 6, 8, 2, 1, 3, 4, 6]
# ]
Read the method each_slice(n)
Iterates the given block for each slice of n elements. If no block is given, returns an enumerator.

Resources