How can I compare lists properly? - for-loop

So I am trying to teach myself some coding and decided to create a little lotto simulator but I just cannot manage to get the program to compare my four lists properly, what is the matter with my def compList code?.
from random import randint as rnd
myGuess_list = []
myGuess_normal = []
myGuess_bonus = []
numbers =[]
drawNumbers = []
normalNumbers = []
bonusNumbers = []
normal_correct = 0
bonus_correct = 0
CORRECT_list = []
BONUS_list = []
winnings = 0
def main():
# generate list of possible numbers
i = 0
for i in range(0, 34):
i += 1
numbers.append(i)
print(numbers)
# draw random numbers from list as lists guessed
def myGuess():
for i in range(0, 10):
numbers = rnd(1, 34)
while numbers in myGuess_list:
numbers = rnd(1, 34)
myGuess_list.append(numbers)
myGuess_list.sort()
myGuess_normal = myGuess_list[0:7]
myGuess_bonus = myGuess_list[-3:]
return myGuess_normal, myGuess_bonus
print(myGuess())
# drawing the lotto numbers from the pool of numbers
def drawNumber(numbers, N):
for i in range(0, N):
number = random.choice(numbers)
while number in drawNumbers:
number = random.choice(numbers)
drawNumbers.append(number)
drawNumbers.sort()
normalNumbers = drawNumbers[0:7]
bonusNumbers = drawNumbers[-3:]
return normalNumbers, bonusNumbers
print(drawNumber(numbers, 10))
comparing list drawn list A with guessed list B and drawn list C with guessed list D
def compList(A, B, C, D):
global normal_correct
global bonus_correct
for i in A and j in C:
if i in B:
normal_correct += 1
CORRECT_list.append(i)
elif j in D:
bonus_correct += 1
BONUS_list.append(j)
print(CORRECT_list + BONUS_list)
return normal_correct, bonus_correct
print(compList(normalNumbers, myGuess_normal, bonusNumbers, myGuess_bonus))
calculate winnings base on previous function
def Winnings(normal_correct, bonus_correct):
global winnings
i = 0
for i in range(0, 10):
i += 1
if normal_correct <= 3:
winnings = 0 - 5
elif normal_correct == 4:
winnings = 45 - 5
elif normal_correct == 5:
winnings = 100 - 5
elif normal_correct == 6:
winnings = 3695 - 5
elif normal_correct == 6 and bonus_correct == 1:
winnings = 169410 - 5
elif normal_correct == 7:
winnings = 'JACKPOT!!'
return winnings
print(Winnings(normal_correct, bonus_correct))
calling main
main()

Related

Algorithm Challenge number formatting problem

Invoice numbers are numeric only with any number of digits. To format one correctly, group the digits in group of three plus a group of any remainder, but never leave one digit by itself, unless it's a one digit number. Eg these are all correct formatting
123
12-34
6
783-907-23-45
And these are not
123-4
98-456
There's one more catch user input is passed directly to the function and you never know what characters users might type. Ignore any part of the input that is not digit
Invoice.format_number should always return a string
module Invoice
def self.format_number(str)
return ""
end
end
puts Invoice.format_number("ab1234")
What I have tried
1st approach
arr = []
str.chars.each do |elem|
val = elem =~ /\A[-+]?[0-9]*\.?[0-9]+\Z/
arr << elem if val == 0
end
num_of_digits = arr.length
pairs_of_two = 0
pairs_of_three = 0
if num_of_digits > 5
while num_of_digits > 0 do
break if num_of_digits <= 3
if num_of_digits >= 3 && (num_of_digits % 3 == 0 || num_of_digits % 3 == 2)
pairs_of_three += 1
num_of_digits -= 3
elsif num_of_digits % 2 == 0 || num_of_digits % 2 == 1
pairs_of_two += 1
num_of_digits -= 2
end
end
end
2nd approach
arr = []
str.chars.each do |elem|
val = elem =~ /\A[-+]?[0-9]*\.?[0-9]+\Z/
arr << elem if val == 0
end
len = arr.length - 1
if arr.length > 4
str = ""
i = 0
while i < len do
if arr[i..i+3].length == 4
str << arr[i..i+2].join + "-"
i += 3
elsif arr[i..i+2].length == 3
str << arr[i..i+1].join + "-"
i += 2
elsif arr[i..i+1].length == 2
str << arr[i..i+1].join
i += 2
elsif !arr[i].nil?
str << arr[i]
i += 1
end
end
puts str
else
if arr.length <= 3
puts arr.join
else
puts arr[0..1].join + "-" + arr[2..3].join
end
end
But none of them is correct
Here is the function invoice_number in python
def invoice_number(invoice):
s = ''.join(x for x in invoice if x <= '9' and x >= '0')
n = len(s)
if n <= 3:
return s
w = ''
i = 0
while i + 3 <= n:
for j in range(0, 3):
w += s[i + j]
i += 3
w += ('-')
m = n - i
if m == 0: return w[:-1]
if m == 1: return w[:m-3] + '-' + s[-2:]
return w + s[i:]
Testing
print(invoice_number('1234567'))
print(invoice_number('12345678'))
print(invoice_number('abc123456789'))
print(invoice_number('1234abc5678xyz9foobar'))
123-45-67
123-456-78
123-456-789
123-456-789
Eliminating non-digits is easy with re. For your format, the key is to figure our the "right" splitting indices.
Here is a try:
import re
def splits(n, k):
idx = [(i, min(n, i+k)) for i in range(0, n, k)]
if len(idx) > 1:
(a, b), (c, d) = idx[-2:]
if d - c < 2:
idx[-2:] = [(a, b - 1), (c - 1, d)]
return idx
def myformat(s):
s = re.sub(r'[^0-9]+', '', s)
parts = [s[a:b] for a, b in splits(len(s), 3)]
return '-'.join(parts)
Tests:
>>> myformat('123')
123
>>> myformat('1234')
12-34
>>> myformat('6')
6
>>> myformat('7839072345')
783-907-23-45
As the question was asked for ruby, adding solution for ruby. (The inspiration of the code is mostly from #yuri answer)
def format_invoice(invoice)
# only numbers are allowed
invoice = invoice.tr("^0-9","")
#puts invoice
return invoice if(invoice.length <= 3)
formatted_invoice = ''
i = 0
# Loop to divide the invoice in group of 3
while i + 3 <= invoice.length do
for j in 0..2 do
formatted_invoice += invoice[i + j]
end
i += 3
formatted_invoice += ('-')
end
m = invoice.length - i
return formatted_invoice[0..-2] if m == 0
return formatted_invoice[0..m-4] + '-' + invoice[-2..-1] if m == 1
return formatted_invoice + invoice[i..-1]
end
Testing
puts format_invoice('abc1') # 1
puts format_invoice('abc123') # 123
puts format_invoice('abc123A4') # 12-34
puts format_invoice('1234567') # 123-45-67
puts format_invoice('12345678') # 123-456-78
puts format_invoice('abc123456789') # 123-456-789
puts format_invoice('1234a#c5678xyz9foobar') # 123-456-789

Run-time error in my realization of deque in Python3

Could you please help me to find an error in the realization of deque? There is a restriction on the number of possible elements in the deque (namely 100).
I suppose that my code has mistakes because it runs out with a run-time error when I am trying to pass it on the contest. The problem is that when I seek to
find this mistake manually I can't get such an error.
Here is my code:
def push_front(dequeue, elem):
global dequeuestart
dequeue[dequeuestart] = elem
dequeuestart -= 1
print('ok')
def push_back(dequeue, elem):
global dequeueend
dequeue[dequeueend] = elem
dequeueend += 1
print('ok')
def pop_front(dequeue):
global dequeuestart
dequeuestart += 1
return dequeue[dequeuestart]
def pop_back(dequeue):
global dequeueend
dequeueend -= 1
return dequeue[dequeueend]
def front(dequeue):
return dequeue[dequeuestart + 1]
def back(dequeue):
return dequeue[dequeueend - 1]
def size(dequeue):
return dequeueend - dequeuestart - 1
def clear(dequeue):
global dequeuestart
global dequeueend
dequeuestart = 99
dequeueend = 100
print('ok')
def exit(dequeue):
print('bye')
dequeue = ['None' for i in range(200)]
dequeuestart = 99
dequeueend = 100
line = input()
while line:
elems = line.split()
if elems[0] == 'push_front':
push_front(dequeue, elems[1])
elif elems[0] == 'push_back':
push_back(dequeue, int(elems[1]))
elif elems[0] == 'pop_front':
print(pop_front(dequeue))
elif elems[0] == 'pop_back':
print(pop_back(dequeue))
elif elems[0] == 'front':
print(front(dequeue))
elif elems[0] == 'back':
print(back(dequeue))
elif elems[0] == 'size':
print(size(dequeue))
elif elems[0] == 'clear':
clear(dequeue)
else:
exit(dequeue)
break
line = input()
Thanks in advance!

Ruby: Why is my Code false?

Trying to multiply each number by array position, and it's coming out false:
def the_sum(number)
i = 0
number = 0
ans = 0
while i < 0
ans = string[idx] * string.index
i += idx
end
return ans
end
test =
the_sum([2, 3]) == 3 # (2*0) + (3*1)
the_sum([2, 3, 5]) == 13 # (2*0) + (3*1) + (5*2)
and it comes out false?
There are a few problems here
def the_sum(number)
i = 0
number = 0 # You just cleared your input variable!
ans = 0
while i < 0 # You previously i = 0 so this will never be true
ans = string[idx] * string.index
i += idx
end
return ans # Ans is and was always 0
end
This can be fixed by calling each_with_index on the Array that you're passing.
def the_array_sum(array)
ans = 0
array.each_with_index do |val, index|
ans += val * index
end
return ans
end
the_array_sum([2, 3]) == 3
# => true
the_array_sum([2, 3, 5]) == 13
# => true

Partial Fibonacci Sum, how to improve performance?

I need to improve the performance of this algorithm. I believe the answer lies in the application of the pisano period.
This algorithm must return the last digit of the sum of fib numbers from f(m) to f(n).
Here is what I have so far:
def fib(n)
a = []
a << 0 << 1
(n+1).times do |i|
a << a[-1] + a[-2]
end
a[n]
end
def fib_partial_sum(m, n)
if n == m
fib(m) % 10
else
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
The last digit of any fib num repeats every 60 numbers. Therefore, we can do this, n, m = n % 60, m % 60. An improvement, but not quite there yet, fails on input 567717153638 567717153638):
def fib(n)
a = []
a << 0 << 1
(n+1).times do |i|
a << a[-1] + a[-2]
end
a[n]
end
def fib_partial_sum(m, n)
if n == m
fib(m)
else
m = m % 60
n = n % 60
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
Here is a nice solution to the problem, it passes all time and memory constraints.
This way you never have to calculate a fib num greater that f(60). It can handle very large inputs efficiently.
def fib(n)
a, b = 0, 1
(n-1).times do
a, b = b, (a + b) % 10
end
b
end
def fib_partial_sum(m, n)
if n == m
fib(m % 60)
else
m = m % 60
n = n % 60
m = fib(m + 1) - 1
n = fib(n + 2) - 1
(n - m) % 10
end
end
if __FILE__ == $0
m, n = gets.split().map(&:to_i)
puts "#{fib_partial_sum(m, n)}"
end
(Max time used: 0.05/5.00, max memory used: 8699904/536870912.)
The following requires only a single pass of the numbers between zero and at most [n,m+60].min, where m..n is the range of interest, and has a minimal memory requirement. It makes use of #nloveladyallen's observation that the last digit of Fibonacci numbers has a periodicity of 60.
Code
def fib_last(m,n)
n -= 60*((n-m)/60)
fib_sum(m,n) % 10
end
def fib_sum(m,n)
return nil if m < 0 || m > n
return n if n < 2
next_to_last, last = fib(m-1)
(m..n).reduce(0) do |tot,_|
current = next_to_last + last
next_to_last = last
last = current
tot + current
end
end
def fib(m)
next_to_last, last = -1, 1
0.upto(m).each do |n|
current = next_to_last + last
next_to_last, last = last, current
end
[next_to_last, last]
end
Example
m, n = 6, 12
(n+1).times { |i| puts "#{i}: #{fib(i)}" }
0: [0, 0]
1: [0, 1]
2: [1, 1]
3: [1, 2]
4: [2, 3]
5: [3, 5]
6: [5, 8]
7: [8, 13]
8: [13, 21]
9: [21, 34]
10: [34, 55]
11: [55, 89]
12: [89, 144]
fib_last(6,12) #=> 4 (fib_sum(6,12) #=> 8 + 13 + 21 + 34 + 55 + 89 + 144 = 364)
fib_last(1,2) #=> 2 (fib_sum(1,2) #=> 1 + 1 = 2)
fib_last(1,3) #=> 4 (fib_sum(1,3) #=> 1 + 1 + 2 = 4)
fib_last(1,4) #=> 7 (fib_sum(1,4) #=> 1 + 1 + 2 + 3 = 7)
fib_last(2,3) #=> 3 (fib_sum(2,3) #=> 1 + 2 = 3)

Ruby FizzBuzz using arrays, my logic seems right but it is getting an error

FizzBuzz, a classic problem, returns all the numbers up to N with a slight twist. If a number is divisible by 3, it is replaced with "fizz". If it's divisible by 5, it's replaced with "buzz". If it's divisible by both, it's replaced with "fizzbuzz"
I keep getting this Error message:
comparison of Fixnum with nil failed
Can someone explain this error message to me please? Also why is the code not working?
def fizz_buzz(n)
arr = (1..n).to_a
i = 0
while arr[i] < arr[n]
if i % 3 == 0 && i % 5 == 0
arr[i] = 'fizzbuzz'
elsif i % 3 == 0
arr[i] = 'fizz'
elsif i % 5 == 0
arr[i] = 'buzz'
else
arr[i] = i
i += 1
end
end
return arr
end
fizz_buzz(12)
Your conditions are just a bit off, give this a try:
def fizz_buzz(n)
arr = (1..n).to_a
i = 0
while i < n
if arr[i] % 3 == 0 && arr[i] % 5 == 0
arr[i] = 'fizzbuzz'
elsif arr[i] % 3 == 0
arr[i] = 'fizz'
elsif arr[i] % 5 == 0
arr[i] = 'buzz'
end
i+=1
end
return arr
end
Trying to access arr[n] puts you outside the bounds of the array which returns nil in Ruby.
You can update the code the ruby way, by using blocks and guards, I don't remember last time I used a while loop in ruby :)
Also, Array.new accepts a block as an argument which you can exploit to build your Array in a single step:
def fizz_buzz(n)
Array.new(n) do |index|
x = index + 1
case
when x % 3 == 0 && x % 5 == 0 then "fizzbuzz"
when x % 3 == 0 then "fizz"
when x % 5 == 0 then "buzz"
else x
end
end
end
Notice I used 1 as a base index and not 0, you can just remove x = index + 1 and replace x with index to have it working in a zero index base
A solution with a block instead of the while loop, and guards
def fizz_buzz(n)
arr = (1..n).to_a
0.upto(n - 1) do |i|
arr[i] = "fizzbuzz" and next if i % 3 == 0 && i % 5 == 0
arr[i] = "fizz" and next if i % 3 == 0
arr[i] = "buzz" if i % 5 == 0
end
arr
end
#brad-melanson beat me to the straight-forward answer to your question, so I'll share an answer which uses some common Ruby idioms (passing a range to the Array constructor and map), which simplify things, prevent you from having to do any iteration bookkeeping and prevent the possibility of off-by-one errors, out-of-bounds errors, etc.
def fizz_buzz(n)
Array(1..12).map do |n|
if n % 3 == 0 && n % 5 == 0
'fizzbuzz'
elsif n % 3 == 0
'fizz'
elsif n % 5 == 0
'buzz'
else
n
end
end
end
result = fizz_buzz 12
# result => [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz"]

Resources