collatz sequence - try except; float number input - collatz

i was trying to make a simple collatz sequence with the following code
number = int(input("Please insert number: \n"))
def collatz():
if number % 2 == 0:
print(number // 2)
elif number % 2 == 1:
print(number * 3 + 1)
collatz()
so, if number is even, then collatz() should print number // 2 and return this value. If number is odd, then collatz() should print and return 3 * number + 1..
the excercise also asks me to implement try & except statements if the user inputs a float. My idea was as following:
number = int(input("Please insert number: \n"))
def collatz():
if number % 2 == 0:
print(number // 2)
elif number % 2 == 1:
print(number * 3 + 1)
try:
collatz()
except ValueError:
print(abs(number))
it doesn't work giving me
ValueError: invalid literal for int() with base 10: '1.2'
although the try except statement what am i doing wrong?

Related

Ruby: find multiples of 3 and 5 up to n. Can't figure out what's wrong with my code. Advice based on my code please

I have been attempting the test below on codewars. I am relatively new to coding and will look for more appropriate solutions as well as asking you for feedback on my code. I have written the solution at the bottom and for the life of me cannot understand what is missing as the resultant figure is always 0. I'd very much appreciate feedback on my code for the problem and not just giving your best solution to the problem. Although both would be much appreciated. Thank you in advance!
The test posed is:
If we list all the natural numbers below 10 that are multiples of 3 or
5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Finish the solution so that it returns the sum of all the multiples of
3 or 5 below the number passed in. Additionally, if the number is
negative, return 0 (for languages that do have them).
Note: If the number is a multiple of both 3 and 5, only count it once.
My code is as follows:
def solution(number)
array = [1..number]
multiples = []
if number < 0
return 0
else
array.each { |x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
}
end
return multiples.sum
end
In a situation like this, when something in your code produces an unexpected result you should debug it, meaning, run it line by line with the same argument and see what each variable holds. Using some kind of interactive console for running code (like irb) is very helpfull.
Moving to your example, let's start from the beginning:
number = 10
array = [1..number]
puts array.size # => 1 - wait what?
puts array[0].class # => Range
As you can see the array variable doesn't contain numbers but rather a Range object. After you finish filtering the array the result is an empty array that sums to 0.
Regardless of that, Ruby has a lot of built-in methods that can help you accomplish the same problem typing fewer words, for example:
multiples_of_3_and_5 = array.select { |number| number % 3 == 0 || number % 5 == 0 }
When writing a multiline block of code, prefer the do, end syntax, for example:
array.each do |x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
end
I'm not suggesting that this is the best approach per se, but using your specific code, you could fix the MAIN problem by editing the first line of your code in one of 2 ways:
By either converting your range to an array. Something like this would do the trick:
array = (1..number).to_a
or by just using a range INSTEAD of an array like so:
range = 1..number
The latter solution inserted into your code might look like this:
number = 17
range = 1..number
multiples = []
if number < 0
return 0
else range.each{|x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
}
end
multiples.sum
#=> 60
The statement return followed by end suggests that you were writing a method, but the def statement is missing. I believe that should be
def tot_sum(number, array)
multiples = []
if number < 0
return 0
else array.each{|x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
}
end
return multiples.sum
end
As you point out, however, this double-counts numbers that are multiples of 15.
Let me suggest a more efficient way of writing that. First consider the sum of numbers that are multiples of 3 that do not exceed a given number n.
Suppose
n = 3
m = 16
then the total of numbers that are multiples of three that do not exceed 16 can be computed as follows:
3 * 1 + 3 * 2 + 3 * 3 + 3 * 4 + 3 * 5
= 3 * (1 + 2 + 3 + 4 + 5)
= 3 * 5 * (1 + 5)/2
= 45
This makes use of the fact that 5 * (1 + 5)/2 equals the sum of an algebraic series: (1 + 2 + 3 + 4 + 5).
We may write a helper method to compute this sum for any number n, with m being the number that multiples of n cannot exceed:
def tot_sum(n, m)
p = m/n
n * p * (1 + p)/2
end
For example,
tot_sum(3, 16)
#=> 45
We may now write a method that gives the desired result (remembering that we need to account for the fact that multiples of 15 are multiples of both 3 and 5):
def tot(m)
tot_sum(3, m) + tot_sum(5, m) - tot_sum(15, m)
end
tot( 9) #=> 23
tot( 16) #=> 60
tot(9999) #=> 23331668

How to iterate over the digits of a number in MIPS?

I have a task where I need to take a number, e.g. 13002, and print it digit by digit using UART (including non-leading 0's). The UART expects that whatever it prints will go in the $s0 register but I can call it whenever I need using a jal.
This means I need to place a digit in $s0 and jump (the UART code has a jr $ra in it so it will return properly once complete.
My problem is I don't know how to iterate over the digits in the number.
My approach so far is to mod the number by 10 (Because it's a decimal number represented in binary) but that gives me the digits in reverse order.
E.g. 13002 % 10 = 2 (then divide 13002 by 10, integer division will truncate the decimal), 1300 % 10 = 0, divide again by 10, 130 ...so on and so forth.
As mentioned above however, that gives me the digits in reverse order. How would I properly iterate over the number?
I wrote some pseudocode in python but it's having trouble with numbers that have 0's in them:
def iterateOverDigits(n):
while (n >= 10):
x = n
i = 0
while (x >= 10):
x = x // 10
i += 1
print(x)
x = n
x = x % (10 ** i)
n = x
iterateOverDigits(1302) # This prints 132
In [1]: def by_digit(n):
...: for char in str(n):
...: print(char)
...:
In [2]: by_digit(120405)
1
2
0
4
0
5
In [3]:
Change the print statement to the following to remove the newlines between each digit:
print(char, end="")

Efficient algorithm to find the n-th digit in the string 112123123412345

What is an efficient algorithm for finding the digit in nth position in the following string
112123123412345123456 ... 123456789101112 ...
Storing the entire string in memory is not feasible for very large n, so I am looking for an algorithm that can find the nth digit in the above string which works if n is very large (i.e. an alternative to just generating the first n digits of the string).
There are several levels here: the digit is part of a number x, the number x is part of a sequence 1,2,3...x...y and that sequence is part of a block of sequences that lead up to numbers like y that have z digits. We'll tackle these levels one by one.
There are 9 numbers with 1 digit:
first: 1 (sequence length: 1 * 1)
last: 9 (sequence length: 9 * 1)
average sequence length: (1 + 9) / 2 = 5
1-digit block length: 9 * 5 = 45
There are 90 numbers with 2 digits:
first: 10 (sequence length: 9 * 1 + 1 * 2)
last: 99 (sequence length: 9 * 1 + 90 * 2)
average sequence length: 9 + (2 + 180) / 2 = 100
2-digit block length: 90 * 100 = 9000
There are 900 numbers with 3 digits:
first: 100 (sequence length: 9 * 1 + 90 * 2 + 1 * 3)
last: 999 (sequence length: 9 * 1 + 90 * 2 + 900 * 3)
average sequence length: 9 + 180 + (3 + 2,700) / 2 = 1,540.5
3-digit block length: 900 * 1,540.5 = 1,386,450
If you continue to calculate these values, you'll find which block (of sequences up to how many digits) the digit you're looking for is in, and you'll know the start and end point of this block.
Say you want the millionth digit. You find that it's in the 3-digit block, and that this block is located in the total sequence at:
start of 3-digit block: 45 + 9,000 + = 9,045
start of 4-digit block: 45 + 9,000 + 1,386,450 = 1,395,495
So in this block we're looking for digit number:
1,000,000 - 9,045 = 990,955
Now you can use e.g. a binary search to find which sequence the 990,955th digit is in; you start with the 3-digit number halfway in the 3-digit block:
first: 100 (sequence length: 9 + 180 + 1 * 3)
number: 550 (sequence length: 9 + 180 + 550 * 3)
average sequence length: 9 + 180 + (3 + 1650) / 2 = 1,015.5
total sequence length: 550 * 1,015.5 = 558,525
Which is too small; so we try 550 * 3/4 = 825, see if that is too small or large, and go up or down in increasingly smaller steps until we know which sequence the 990,995th digit is in.
Say it's in the sequence for the number n; then we calculate the total length of all 3-digit sequences up to n-1, and this will give us the location of the digit we're looking for in the sequence for the number n. Then we can use the numbers 9*1, 90*2, 900*3 ... to find which number the digit is in, and then what the digit is.
We have three types of structures that we would like to be able to search on, (1) the sequence of concatenating d-digit numbers, for example, single digit:
123456...
or 3-digit:
100101102103
(2) the rows in a section,
where each section builds on the previous section added to a prefix. For example, section 1:
1
12
123
...
or section 3:
1234...10111213...100
1234...10111213...100102
1234...10111213...100102103
<----- prefix ----->
and (3) the full sections, although the latter we can just enumerate since they grow exponentially and help build our section prefixes. For (1), we can use simple division if we know the digit count; for (2), we can binary search.
Here's Python code that also answers the big ones:
def getGreatest(n, d, prefix):
rows = 9 * 10**(d - 1)
triangle = rows * (d + rows * d) // 2
l = 0
r = triangle
while l < r:
mid = l + ((r - l) >> 1)
triangle = mid * prefix + mid * (d + mid * d) // 2
prevTriangle = (mid-1) * prefix + (mid-1) * (d + (mid-1) * d) // 2
nextTriangle = (mid+1) * prefix + (mid+1) * (d + (mid+1) * d) // 2
if triangle >= n:
if prevTriangle < n:
return prevTriangle
else:
r = mid - 1
else:
if nextTriangle >= n:
return triangle
else:
l = mid
return l * prefix + l * (d + l * d) // 2
def solve(n):
debug = 1
d = 0
p = 0.1
prefixes = [0]
sections = [0]
while sections[d] < n:
d += 1
p *= 10
rows = int(9 * p)
triangle = rows * (d + rows * d) // 2
section = rows * prefixes[d-1] + triangle
sections.append(sections[d-1] + section)
prefixes.append(prefixes[d-1] + rows * d)
section = sections[d - 1]
if debug:
print("section: %s" % section)
n = n - section
rows = getGreatest(n, d, prefixes[d - 1])
if debug:
print("rows: %s" % rows)
n = n - rows
d = 1
while prefixes[d] < n:
d += 1;
if prefixes[d] == n:
return 9;
prefix = prefixes[d - 1]
if debug:
print("prefix: %s" % prefix)
n -= prefix
if debug:
print((n, d, prefixes, sections))
countDDigitNums = n // d
remainder = n % d
prev = 10**(d - 1) - 1
num = prev + countDDigitNums
if debug:
print("num: %s" % num)
if remainder:
return int(str(num + 1)[remainder - 1])
else:
s = str(num);
return int(s[len(s) - 1])
ns = [
1, # 1
2, # 1
3, # 2
100, # 1
2100, # 2
31000, # 2
999999999999999999, # 4
1000000000000000000, # 1
999999999999999993, # 7
]
for n in ns:
print(n)
print(solve(n))
print('')
Well, you have a series of sequences each increasing by a single number.
If you have "x" of them, then the sequences up to that point occupy x * (x + 1) / 2 character positions. Or, another way of saying this is that the "x"s sequence starts at x * (x - 1) / 2 (assuming zero-based indexing). These are called triangular numbers.
So, all you need to do is to find the "x" value where the cumulative amount is closest to a given "n". Here are three ways:
Search for a closed from solution. This exists, but the formula is rather complicated. (Here is one reference for the sum of triangular numbers.)
Pre-calculate a table in memory with values up to, say, 1,000,000. that will get you to 10^10 sizes.
Use a "binary" search and the formula. So, generate the sequence of values for 1, 2, 4, 8, and so on and then do a binary search to find the exact sequence.
Once you know the sequence where the value lies, determining the value is simply a matter of arithmetic.

How many ways can we split a number into k unequal summands?

I am taking a challenge online and came across this question, where I need to find the number of ways to split a number 'n' into 'k' unequal summands. For example,
3 - Can be split into 2 and 1.
4 - Can be split into 3 and 1. Note: We cannot do 2 and 2 because, they are equal
5 - (3,2) and (4,1). and so on..
Is there any algorithm for this.
Code in python:
def minArgument(x):
s = 0
i = 1
while s < x:
s += i
i += 1
return i - 1
def maxArgument(x):
return x - 1
def number_of_sumsDP(M, K):
lowerLimit = minArgument(M)
if K < lowerLimit:
return 0
else:
if K - 1 >= M // 2:
return 1 + number_of_sumsDP(M, K - 1)
else:
return 0
def number_of_sums_simple(n):
if n % 2 == 0:
return n // 2 - 1
else:
return n // 2
for i in range(2, 100):
if number_of_sumsDP(i, maxArgument(i)) != number_of_sums_simple(i):
print("mistake")
print("works")
First thought dynamic programming (number_of_sumsDP(M, K)) - number of sums is equal to number of sums with the biggest possible number (subject - 1) and sums without it (with obvious stop when number is less than min arg - it doesn't make sense to add up to 10 with numbers less than 4 [minArgument] and when we start repeating ourself [if K - 1 < M // 2]).
After few prints it leads to even simpler and much efficient algorithm:
number_of_sums_simple - return division in integers by 2 when odd and the same minus one when even; as a proof I convinced myself that it works.

No of numbers less than a given number with no repeating digits

How can we find the number of numbers less than a given number with no repeating digits in it?
For example the number of such numbers less than 100 is 90. (11, 22, 33,44, 55,66,77,88,99 have repeating digits so are excluded).
Similarly for less than 1000, digits like 101, 110, 122, 202 etc have to be excluded.
Here is a way to make it quicker. Notice that there is a correlation between the number of digits in the max number and the solution (number of numbers which I will call NON)
100 (3 digits) => NON = 10 * 9
1000 (4 digits) => NON = 10 * 9 * 8
10000 (5 digits) => NON = 10 * 9 * 8 * 7
...
10000000000 (11 digits) => NON = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
after one billion you're bound to repeat a digit
You can consider two cases:
numbers shorter than the limit
numbers that that differ from the limit at some digit
The count of d-digit numbers is 9*9*8*... = 9*9!/(9-d)! (the first digit may not be zero). The count of all numbers shorter than d is the count of 0-digit numbers + .. count of d-1-digit numbers. These sums may be precomputed (or even hard-coded).
The count of d-digit numbers with f first digits given is (10-f)*...*(10-(d-1)) = (10-f)!/(10-d)!. You can precomupte the factorials as well.
Pseudocode :
To precompute fac:
- fac = int[10];
- fac[0] = 1;
- for i in 1..10:
- fac[i] = fac[i-1] * i;
To precompute count_shorter:
- cs = int[10];
- cs[0] = 0;
- cs[1] = 1; // if zero is allowed
- for i in 1..10:
- cs[i+1] = cs[i] + 9 * fac[9] / fac[10-i]
- count_shorter = cs;
To determine the count of numbers smaller than d:
- sl = strlen(d)
- if sl > 10
- return count_shorter[11]
- else
- sum = 0
account for shorter numbers:
- sum += count_shorter[sl]
account for same-length numbers; len=count of digits shared with the limit:
- sum += 9* fac[9] / fac[10-sl];
- for every len in 1..{sl-1}:
count the unused digits less than d[len]; credits to #MvG for noting:
- first_opts = d[len]-1;
- for every i in 0..{len-1}:
- if d[i] < d[len]
- first_opts -= 1;
- sum += first_opts * fac[9-len] / fac[10-sl]
- return sum
Here is some code that does this. Comments in the code. The basic idea is that you iterate over the digits of the last counted number one at a time, and for every digit position you can count the numbers that have the same digits prior to that position but a smaller digit at that current position. The functions build upon one another, so the cntSmaller function at the very end is the one you'd actually call, and also the one with the most detailed comments. I've checked that this agrees with a brute-force implementation for all arguments up to 30000. I've done extensive comparisons against alternate implementations, so I'm fairly confident that this code is correct.
from math import factorial
def take(n, r):
"""Count ways to choose r elements from a set of n without
duplicates, taking order into account"""
return factorial(n)/factorial(n - r)
def forLength(length, numDigits, numFirst):
"""Count ways to form numbers with length non-repeating digits
that take their digits from a set of numDigits possible digits,
with numFirst of these as possible choices for the first digit."""
return numFirst * take(numDigits - 1, length - 1)
def noRepeated(digits, i):
"""Given a string of digits, recursively compute the digits for a
number which is no larger than the input and has no repeated
digits. Recursion starts at i=0."""
if i == len(digits):
return True
while digits[i] in digits[:i] or not noRepeated(digits, i + 1):
digits[i] -= 1
for j in range(i + 1, len(digits)):
digits[j] = 9
if digits[i] < 0:
digits[i] = 9
return False
return True
def lastCounted(n):
"""Compute the digits of the last number that is smaller than n
and has no repeated digits."""
digits = [int(i) for i in str(n - 1)]
while not noRepeated(digits, 0):
digits = [9]*(len(digits) - 1)
while digits[0] == 0:
digits = digits[1:]
assert len(digits) == len(set(digits))
return digits
def cntSmaller(n):
if n < 2:
return 0
digits = lastCounted(n)
cnt = 1 # the one from lastCounted is guaranteed to get counted
l = len(digits)
for i in range(1, l):
# count all numbers with less digits
# first digit non-zero, rest all other digits
cnt += forLength(i, 10, 9)
firstDigits = set(range(10))
for i, d in enumerate(digits):
# count numbers which are equal to lastCounted up to position
# i but have a smaller digit at position i
firstHere = firstDigits & set(range(d)) # smaller but not duplicate
if i == 0: # this is the first digit
firstHere.discard(0) # must not start with a zero
cnt += forLength(l - i, 10 - i, len(firstHere))
firstDigits.discard(d)
return cnt
Edit: cntSmaller(9876543211) returns 8877690 which is the maximum number of numbers you can form with non-repeating digits. The fact that this is more than 10!=3628800 had me confused for a while, but this is correct: when you consider your sequences padded to length 10, then sequences of leading zeros are allowed in addition to a zero somewhere in the number. This increases the count above that of the pure permutations.

Resources