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.
Related
Hy, I have misunderstanding with this code
By the task I should write a function to find the longest common prefix string amongst an array of strings.
If there is no common prefix, return an empty string "".
So my soluthion :
def longestCommonPrefix(strs: Array[String]): String = {
val size = strs.length
if (size == 0) {
" "
} else {
val j = strs.sortWith(_.length < _.length)
val minStr = Math.min(j(0).length, j(size - 1).length)
var i: Int = 0
while (i < minStr && j(0).take(i) == j(size - 1).take(i))
i=i+1
val pre = j(0).substring(0, i-1)
pre
}
}
Example: val name = Array("flower","flow","flight")
print(longestCommonPrefix(name))
output: fl
And it's correct , but when I put Array("") I have en error
String index out of range: -1
why this condition isn't work ?
if (size == 0) { " "}
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'm trying to retrieve values from Firebase and calculate the means of those values by looping the sum of every path in Firebase and keep in each variable.
Then, I divide by the number of checkCount.
But it shows me an error like this...
Error: attribute d: Expected number, "… A 50 50 0 0 1 NaN
NaN".
I found that this error come from the > Summand values
this.total1 = (this.total1 / this.checkedCount) //Line 35 - 42
How can I solve this? :((
total1: number = 0
total2: number = 0
total3: number = 0
total4: number = 0
total5: number = 0
total6: number = 0
total7: number = 0
total8: number = 0
checkedCount: number = 0
calculateProfile() {
this.afAuth.authState.take(1).subscribe(data => {
if (data && data.email && data.uid) {
var userRef = firebase.database().ref('/profile').child(data.uid)
for (let i = 1; i < 10; i++) { // Loop all the 1st paths in Firebase
for (let j = 1; j < 5; j++) { // Loop all the 2nd paths in Firebase
userRef.child('/unit').child('' + (i)).child('/lesson').child('' + (j))
.on('value', snap => {
++this.checkedCount //count every path for division
this.total1 += snap.val().count1
this.total2 += snap.val().count2
this.total3 += snap.val().count3
this.total4 += snap.val().count4
this.total5 += snap.val().count5
this.total6 += snap.val().count6
this.total7 += snap.val().count7
this.total8 += snap.val().count8
}//End if
})//End on
}
}
this.total1 = (this.total1 / this.checkedCount)
this.total2 = (this.total2 / this.checkedCount)
this.total3 = (this.total3 / this.checkedCount)
this.total4 = (this.total4 / this.checkedCount)
this.total5 = (this.total5 / this.checkedCount)
this.total6 = (this.total6 / this.checkedCount)
this.total7 = (this.total7 / this.checkedCount)
this.total8 = (this.total8 / this.checkedCount)
}
})
}
This solved yesterday..
It might be the problem of using the same variable.
So, I declare variables for keeping those divided data.
I gonna close this. :D
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"
For a mobile shop application, I need to validate an IMEI number. I know how to validate based on input length, but is their any other mechanism for validating the input number? Is there any built-in function that can achieve this?
Logic from any language is accepted, and appreciated.
A search suggests that there isn't a built-in function that will validate an IMEI number, but there is a validation method using the Luhn algorithm.
General process:
Input IMEI: 490154203237518
Take off the last digit, and remember it: 49015420323751 & 8. This last digit 8 is the validation digit.
Double each second digit in the IMEI: 4 18 0 2 5 8 2 0 3 4 3 14 5 2 (excluding the validation digit)
Separate this number into single digits: 4 1 8 0 2 5 8 2 0 3 4 3 1 4 5 2 (notice that 18 and 14 have been split).
Add up all the numbers: 4+1+8+0+2+5+8+2+0+3+4+3+1+4+5+2 = 52
Take your resulting number, remember it, and round it up to the nearest multiple of ten: 60.
Subtract your original number from the rounded-up number: 60 - 52 = 8.
Compare the result to your original validation digit. If the two numbers match, your IMEI is valid.
The IMEI given in step 1 above is valid, because the number found in step #7 is 8, which matches the validation digit.
According to the previous answer from Karl Nicoll i'm created this method in Java.
public static int validateImei(String imei) {
//si la longitud del imei es distinta de 15 es invalido
if (imei.length() != 15)
return CheckImei.SHORT_IMEI;
//si el imei contiene letras es invalido
if (!PhoneNumber.allNumbers(imei))
return CheckImei.MALFORMED_IMEI;
//obtener el ultimo digito como numero
int last = imei.charAt(14) - 48;
//duplicar cada segundo digito
//sumar cada uno de los digitos resultantes del nuevo imei
int curr;
int sum = 0;
for (int i = 0; i < 14; i++) {
curr = imei.charAt(i) - 48;
if (i % 2 != 0){
// sum += duplicateAndSum(curr);
// initial code from Osvel Alvarez Jacomino contains 'duplicateAndSum' method.
// replacing it with the implementation down here:
curr = 2 * curr;
if(curr > 9) {
curr = (curr / 10) + (curr - 10);
}
sum += curr;
}
else {
sum += curr;
}
}
//redondear al multiplo de 10 superior mas cercano
int round = sum % 10 == 0 ? sum : ((sum / 10 + 1) * 10);
return (round - sum == last) ? CheckImei.VALID_IMEI_NO_NETWORK : CheckImei.INVALID_IMEI;
}
IMEI can start with 0 digit. This is why the function input is string.
Thanks for the method #KarlNicol
Golang
func IsValid(imei string) bool {
digits := strings.Split(imei, "")
numOfDigits := len(digits)
if numOfDigits != 15 {
return false
}
checkingDigit, err := strconv.ParseInt(digits[numOfDigits-1], 10, 8)
if err != nil {
return false
}
checkSum := int64(0)
for i := 0; i < numOfDigits-1; i++ { // we dont need the last one
convertedDigit := ""
if (i+1)%2 == 0 {
d, err := strconv.ParseInt(digits[i], 10, 8)
if err != nil {
return false
}
convertedDigit = strconv.FormatInt(2*d, 10)
} else {
convertedDigit = digits[i]
}
convertedDigits := strings.Split(convertedDigit, "")
for _, c := range convertedDigits {
d, err := strconv.ParseInt(c, 10, 8)
if err != nil {
return false
}
checkSum = checkSum + d
}
}
if (checkSum+checkingDigit)%10 != 0 {
return false
}
return true
}
I think this logic is not right because this working only for the specific IMEI no - 490154203237518 not for other IMEI no ...I implement the code also...
var number = 490154203237518;
var array1 = new Array();
var array2 = new Array();
var specialno = 0 ;
var sum = 0 ;
var finalsum = 0;
var cast = number.toString(10).split('');
var finalnumber = '';
if(cast.length == 15){
for(var i=0,n = cast.length; i<n; i++){
if(i !== 14){
if(i == 0 || i%2 == 0 ){
array1[i] = cast[i];
}else{
array1[i] = cast[i]*2;
}
}else{
specialno = cast[14];
}
}
for(var j=0,m = array1.length; j<m; j++){
finalnumber = finalnumber.concat(array1[j]);
}
while(finalnumber){
finalsum += finalnumber % 10;
finalnumber = Math.floor(finalnumber / 10);
}
contno = (finalsum/10);
finalcontno = Math.round(contno)+1;
check_specialno = (finalcontno*10) - finalsum;
if(check_specialno == specialno){
alert('Imei')
}else{
alert('Not IMEI');
}
}else{
alert('NOT imei - length not matching');
}
//alert(sum);
According to the previous answer from Karl Nicoll i'm created this function in Python.
from typing import List
def is_valid_imei(imei: str) -> bool:
def digits_of(s: str) -> List[int]:
return [int(d) for d in s]
if len(imei) != 15 or not imei.isdecimal():
return False
digits = digits_of(imei)
last = digits.pop()
for i in range(1, len(digits), 2):
digits[i] *= 2
digits = digits_of(''.join(map(str, digits)))
return (sum(digits) + last) % 10 == 0
This one is working for me
try:
immie_procesed = list(
map(int, str(request.data.decode("utf-8").split(',')[0])))
last_number = immie_procesed[len(immie_procesed) - 1]
val = sum([sum(map(int, str(int(v)*2))) if i % 2 else int(v)
for i, v in enumerate(immie_procesed[: -1])])
round_value = math.ceil(val / 10) * 10
validation_value = round_value - val
if (validation_value == last_number):
IMEI = request.data.decode("utf-8").split(',')[0]
else:
return "INVALID IMEI"
except:
return 'Something goes wrong in validation process'
I don't believe there are any built-in ways to authenticate an IMEI number. You would need to verify against a third party database (googling suggests there are a number of such services, but presumably they also get their information from more centralised sources).