iteration over a sequence with an implicit type in Python 3.6 - python-3.x

I am trying to iterate over a sequence of numbers. I have this:
from itertools import islice, count
handle = int(input("Please enter a number:")
handler = str(handle)
parameter = []
for i in handler:
parameter.append(i)
print(parameter) #This was for debugging
revised = parameter(count(1[2])) #I'm not sure I'm using the correct syntax here, the purpose is to make revised == parameter[0] and parameter[2]
Ultimately, what I am trying to achieve is to take a sequence of numbers or two, and compare them. For instance, if i[0] == i[1] + i [2] I want to return True, or for that matter if i[0] == i[1] - i[2]. I want the program to iterate over the entire sequence, checking for these types of associations, for instance, 23156 would == true because 2*3 = 6, 2+3 = 5, 5+1 = 6, 2+3+1=6; etc. It's strictly for my own purposes, just trying to make a toy.
When I utilize
revised = parameter(count(1[2])
I am getting an error that says builtins. TYPEERROR, type int is not subscriptable but I explicitly turned the integer input into a string.

Albeit unclear, what you have attempted to describe is hard to explain. It appears to be akin to a Running Total but with restrictions and of various operations, i.e. addition, subtraction and products.
Restrictions
The first two numbers are seeds
The following numbers must accumulate by some operation
The accumulations must progress contiguously
Code
import operator as op
import itertools as it
def accumulate(vals):
"""Return a set of results from prior, observed operations."""
adds = set(it.accumulate(vals)) # i[0] == i[1] + i[2]
muls = set(it.accumulate(vals, op.mul)) # i[0] == i[1] * i[2]
subs = {-x for x in it.accumulate(vals, func=op.sub)} # i[0] == i[1] - i[2]
#print(adds, muls, subs)
return adds | muls | subs
def rolling_acc(vals):
"""Return accumulations by sweeping all contiguous, windowed values."""
seen = set()
for i, _ in enumerate(vals):
window = vals[i:]
if len(window) >= 3:
seen |= accumulate(window)
return seen
def is_operable(vals):
"""Return `True` if rolling operations on contiguous elements will be seen."""
s = str(vals)
nums = [int(x) for x in s]
ahead = nums[2:]
accums = rolling_acc(nums)
#print(ahead, accums)
return len(set(ahead) & accums) == len(ahead)
Tests
assert is_operable(23156) == True
assert is_operable(21365) == False # {2,3} non-contiguous
assert is_operable(2136) == True
assert is_operable(11125) == True

Related

name 'count' is not defined in python

I have this code in python and I am trying to make a counter for the iteration of the binary search (yeah I know it is incomplete...), but I am stuck with the variable inside the function, when i try to print the variable count I get this error
name 'count' is not defined in python
can someone explain why i get this error?
import csv
def binarySearch(arr, l, r, x):
count=0
while l <= r:
mid = int(l + (r - l) / 2)
# Check if x is present at mid
if arr[mid] == x:
return mid
# If x is greater, ignore left half
elif arr[mid] < x:
l = mid + 1
# If x is smaller, ignore right half
else:
r = mid - 1
# If we reach here, then the element
# was not present
return -1
with open('bl_printed_music_500.csv', newline='', encoding="utf-8-sig") as csvfile:
reader = csv.DictReader(csvfile)
arr=[]
for row in reader:
if row ["Publication date (standardised)"] != "":
arr.append(int(row["Publication date (standardised)"])) #create list for searching
list.sort(arr) #list must be sorted to work
#print (arr)
x = 1850 #year to search
# Function call
result = binarySearch(arr, 0, len(arr) - 1, x)
found = False
if result != -1:
found = True
print(found)
print(count)
I think it's because you defined count in binarySearch but try to use it outside of the method. Try using a global variable (define it outside of binarySearch), it should work.
You can return count as well.
For example:
def myFunc():
x = 5
y = 10
return x,y
a, b = myFunc()
print(a)
print(b)
This will be:
5
10
Note that, I could have written x, y = myFunc(). These x and y are not the same as the ones inside myFunc(). The latter are local to the function.
In your code, you can return your local count variable:
return mid, count #(A)
return -1, count #(A)
And get its value by:
result, count = binarySearch(arr, 0, len(arr)-1, x) #(B)
Again, these two count variables, (A) and (B) are different variables with different scopes.
See, for instance:
https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
Alternatively, if a global variable, as suggested in the other answer, suits you best, you can see an example of its usage in the link.

Convert a number to binary in Python

Given a non-negative integer n, write a function to_binary/ToBinary which returns that number in a binary format.
This is my code but some tests don't pass.
I appreciate it if you help me fix my code:
def to_binary(n):
string = ""
if n > 2:
string = string + str(n % 2)
x = n // 2
while x >= 2:
i = x % 2
string = string + str(i)
x = x // 2
string = string + str(1)
l = len(string)
string[l::-1]
return int(string)
else:
if n == 1:
return 1
if n == 2:
return 10
Few points to note.
Changing the concatenation logic will generate the string in reverse. You won't have to reverse it in the end.
In [10]: s = ''
In [11]: for i in range(5):
...: s = s + str(i)
...:
In [12]: s
Out[12]: '01234'
In [13]: s = ''
In [14]: for i in range(5):
...: s = str(i) + s # add the existing string after i
...:
In [15]: s
Out[15]: '43210'
You don't require a different logic for numbers less than 2. You shouldn't have to hardcode anything unless you're using recursion. In which case, hardcoding is simply the base case.
You are not reversing the string at all.
s[::-1]
This does not reverse a string in-place. Strings in python are immutable. What you can do is,
s = s[::-1]
Not providing the limits in a slice syntax is the same as providing start and end values (0 and length). You don't have to explicitly write s[len(s)::-1].
Your logic is almost correct. Just remove everything and keep the while loop and the code will work.
def to_bin(x):
if x == 0:
return '0'
b = ''
while x > 0:
b = str(x%2) + b
x //= 2
return b
There are of course several ways to do this without writing code just by using the builtin features of python.
You could try the implementing the mathematical method of converting bases into Python. Every number can be expressed as the sum of the powers of a base. For binary, base 2, this would be N*2**n + ... + A*2**3 + B*2**2 + C*2**1 + D*2**0. The hardest part is finding N, but from there we can use divmod to solve for the other variables.
def get_highest_power(num, base=2):
n = 0
while True:
if base**(n+1) >= num:
break
n += 1
return n
def solve_for_coefficients(num, power, base=2):
coefficients = []
for p in range(power, -1, -1):
coef, num = divmod(num, base**p)
coefficients.append(coef)
return coefficients
leading_power = get_highest_power(1000)
coefficients = solve_for_coefficients(1000, leading_power)
In order to get the base conversion, just use something like int(''.join([str(i) for i in coefficients])). This method works for all bases less than 10, since bases after ten require letters (but then again, you could use look at the items in coefficients to get the letters).
If you just want to solve the problem "number to binary string", you could use simple python:
def to_binary(n):
return "{:b}".format(n)
Simply use bin() instead.
def to_binary(n):
return(bin(n)[2:])
to_binary(6)
'110'

Extending current code to include both median and mode

I have this line of code that i used for one assignment, but i can't figure out how to add the median and mode into the code to let it run without error.
def main():
filename = input('File name: ')
num=0
try:
infile = open(filename, 'r')
count = 0
total = 0.0
average = 0.0
maximum = 0
minimum = 0
range1 = 0
for line in infile:
num = int(line)
count = count + 1
total = total + num
if count == 1:
maximum = num
minimum = num
else:
if num > maximum:
maximum = num
if num < minimum:
minimum = num
if count > 0:
average = total / count
range1 = maximum - minimum
I'll jump right in and show you the code. It's a very simple and quite pythonic solution.
Solution
import statistics
def open_file(filename):
try:
return open(filename, 'r')
except OSError as e:
print(e)
return None
def main():
# Read file. Note that we are trusting the user input here without sanitizing.
fd = open_file(input('File name: '))
if fd is None: # Ensure we have a file descriptor
return
data = fd.read() # Read whole file
if data == '':
print("No data in file")
return
lines = data.split('\n') # Split the data into a list of strings
# We need to convert the list of strings to a list of integers
# I don't know a pythonic way of doing this.
for number, item in enumerate(lines):
lines[number] = int(item)
total_lines = len(lines)
total_sum = sum(lines)
maximum = max(lines)
minimum = min(lines)
# Here is the python magic, no need to reinvent the wheel!
mean = statistics.mean(lines) # mean == average
median = statistics.median(lines)
mode = "No mode!"
try:
mode = statistics.mode(lines)
except statistics.StatisticsError as ec:
pass # No mode, due to having the same quantity of 2 or more different values
print("Total lines: " + str(total_lines))
print("Sum: " + str(total_sum))
print("Max: " + str(maximum))
print("Min: " + str(minimum))
print("Mean: " + str(mean))
print("Median: " + str(median))
print("Mode: " + str(mode))
if __name__ == '__main__':
main()
Explanation
Generally, in python, it's safe to assume that if you want to calculate any mundane value using a well known algorithm, there will already be a function written for you to do just that. No need to reinvent the wheel!
These functions aren't usually hard to find online either. For instance, you can find suggestions regarding the statistics library by googling python calculate the median
Although you have the solution, I strongly advise looking through the source code of the statistics library (posted below), and working out how these functions work for yourself. It will help your grow as a developer and mathematician.
statistics.py
mean
def mean(data):
"""Return the sample arithmetic mean of data.
>>> mean([1, 2, 3, 4, 4])
2.8
>>> from fractions import Fraction as F
>>> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)])
Fraction(13, 21)
>>> from decimal import Decimal as D
>>> mean([D("0.5"), D("0.75"), D("0.625"), D("0.375")])
Decimal('0.5625')
If ``data`` is empty, StatisticsError will be raised.
"""
if iter(data) is data:
data = list(data)
n = len(data)
if n < 1:
raise StatisticsError('mean requires at least one data point')
T, total, count = _sum(data)
assert count == n
return _convert(total/n, T)
median
def median(data):
"""Return the median (middle value) of numeric data.
When the number of data points is odd, return the middle data point.
When the number of data points is even, the median is interpolated by
taking the average of the two middle values:
>>> median([1, 3, 5])
3
>>> median([1, 3, 5, 7])
4.0
"""
data = sorted(data)
n = len(data)
if n == 0:
raise StatisticsError("no median for empty data")
if n%2 == 1:
return data[n//2]
else:
i = n//2
return (data[i - 1] + data[i])/2
mode
def mode(data):
"""Return the most common data point from discrete or nominal data.
``mode`` assumes discrete data, and returns a single value. This is the
standard treatment of the mode as commonly taught in schools:
>>> mode([1, 1, 2, 3, 3, 3, 3, 4])
3
This also works with nominal (non-numeric) data:
>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
'red'
If there is not exactly one most common value, ``mode`` will raise
StatisticsError.
"""
# Generate a table of sorted (value, frequency) pairs.
table = _counts(data)
if len(table) == 1:
return table[0][0]
elif table:
raise StatisticsError(
'no unique mode; found %d equally common values' % len(table)
)
else:
raise StatisticsError('no mode for empty data')

Dynamic Programming Primitive calculator code optimization

I am currently doing coursera course on algorithms. I have successfully completed this assignment. All test cases passed. My code looks messy and I want to know if there is any thing availiable in Python which can help run my code faster. Thanks
The problem statement is as follows: You are given a primitive calculator that can perform the following three operations with
the current number 𝑥: multiply 𝑥 by 2, multiply 𝑥 by 3, or add 1 to 𝑥. Your goal is given a
positive integer 𝑛, find the minimum number of operations needed to obtain the number 𝑛
starting from the number 1.
# Uses python3
import sys
def optimal_sequence(m):
a=[0,0]
for i in range(2,m+1):
if i%3==0 and i%2==0:
a.append(min(a[i//2],a[i//3],a[i-1])+1)
elif i%3==0:
a.append(min(a[i//3],a[i-1])+1)
elif i%2==0:
a.append(min(a[i//2],a[i-1])+1)
else:
a.append((a[i-1])+1)
return backtrack(a,m)
def backtrack(a,m):
result=[]
result.append(m)
current = m
for i in range(a[-1],0,-1):
if current%3==0 and a[current//3]==(i-1):
current=current//3
result.append(current)
elif current%2==0 and a[current//2]==(i-1):
current = current//2
result.append(current)
elif a[current-1]==(i-1):
current = current-1
result.append(current)
return result
n = int(input())
if n == 1:
print(0)
print(1)
sys.exit(0)
a= (optimal_sequence(n))
print(len(a)-1)
for x in reversed(a):
print(x,end=" ")
I would use a breadth first search for number 1 starting from number n. Keep track of the numbers that were visited, so that the search backtracks on already visited numbers. For visited numbers remember which is the number you "came from" to reach it, i.e. the next number in the shortest path to n.
In my tests this code runs faster than yours:
from collections import deque
def findOperations(n):
# Perform a BFS
successor = {} # map number to next number in shortest path
queue = deque() # queue with number pairs (curr, next)
queue.append((n,None)) # start at n
while True:
curr, succ = queue.popleft()
if not curr in successor:
successor[curr] = succ
if curr == 1:
break
if curr%3 == 0: queue.append((curr//3, curr))
if curr%2 == 0: queue.append((curr//2, curr))
queue.append((curr-1, curr))
# Create list from successor chain
result = []
i = 1
while i:
result.append(i)
i = successor[i]
return result
Call this function with argument n:
findOperations(n)
It returns a list.

I made a function to find a word in a list of words by splitting it in half each time -- how does each if statement contribute to the time complexity?

My program is here. It is assumed that lst is a list of words in alphabetical order.
My question is if the time complexity is changed by each if statement.
When compared to just using x in s (which has a time complexity of O(n)), it is faster, right? From what I know the time complexity of this program is O(N/8), unless each if statement counts, in which it should be N/4?.
Thanks for the help.
def is_in(val, lst):
"""
is_in is designed to check if a word is in a list of words in alphabetical order.
:param val: the word to look for
:param lst: the lst of words to check
"""
curlen = len(lst) # saving processing power
if ((curlen == 1) and (lst[0] != val)) or (curlen == 0): # base case
return False
else:
center = curlen // 2
pivot = lst[center]
# print("pivot: " + str(pivot))
# print("val: " + str(val))
if pivot == val: # base case 2
return True
elif pivot > val:
return is_in(val, lst[:center])
else:
return is_in(val, lst[center:])

Resources