Draw a centered triforce surrounded by hyphens using Python - python

I want to draw a triangle of asterisks from a given n which is an odd number and at least equal to 3. So far I did the following:
def main():
num = 5
for i in range(num):
if i == 0:
print('-' * num + '*' * (i + 1) + '-' * num)
elif i % 2 == 0:
print('-' * (num-i+1) + '*' * (i + 1) + '-' * (num-i+1))
else:
continue
if __name__ == "__main__":
main()
And got this as the result:
-----*-----
----***----
--*****--
But how do I edit the code so the number of hyphens corresponds to the desirable result:
-----*-----
----***----
---*****---
--*-----*--
-***---***-
*****-*****

There's probably a better way but this seems to work:
def triangle(n):
assert n % 2 != 0 # make sure n is an odd number
hyphens = n
output = []
for stars in range(1, n+1, 2):
h = '-'*hyphens
s = '*'*stars
output.append(h + s + h)
hyphens -= 1
pad = n // 2
mid = n
for stars in range(1, n+1, 2):
fix = '-'*pad
mh = '-'*mid
s = '*'*stars
output.append(fix + s + mh + s + fix)
pad -= 1
mid -= 2
print(*output, sep='\n')
triangle(5)
Output:
-----*-----
----***----
---*****---
--*-----*--
-***---***-
*****-*****

Think about what it is you're iterating over and what you're doing with your loop. Currently you're iterating up to the maximum number of hyphens you want, and you seem to be treating this as the number of asterisks to print, but if you look at the edge of your triforce, the number of hyphens is decreasing by 1 each line, from 5 to 0. To me, this would imply you need to print num-i hyphens each iteration, iterating over line number rather than the max number of hyphens/asterisks (these are close in value, but the distinction is important).
I'd recommend trying to make one large solid triangle first, i.e.
-----*-----
----***----
---*****---
--*******--
-*********-
***********
since this is a simpler problem to solve and is just one modification away from what you're trying to do (this is where the distinction between number of asterisks and line number will be important, as your pattern changes dependent on what line you're on).
I'll help get you started; for any odd n, the number of lines you need to print is going to be (n+1). If you modify your range to be over this value, you should be able to figure out how many hyphens and asterisks to print on each line to make a large triangle, and then you can just modify it to cut out the centre.

Related

How to make pyramid of a string?

I want to make a pyramid of a string for an exercise.
I just don't know how to do it.
For example:
string = "these***are***just***random***words*"
and the pyramid I want to make is:
t
hes
e***a
re***ju
st***rand
om***words*
How do I do this?
def draw_pyramid(string, size):
if size > 15:
size = 15
if size < 5:
size = 5
l = string * size
for i in range(size + 1):
stars = i
p = l[0:stars]
spaces = size - i
print(" " * spaces + p)
def main():
size = int(input("How many layers do you want it to be?: "))
string = "these***are***just***random***words*"
draw_pyramid(string, size)
if __name__ == '__main__':
main()
Result:
t
th
the
thes
these
these*
these**
these***
these***a
these***ar
You can use string.center() to get the strings nicely aligned in the center. To get the right characters from l I use a start and an end variable:
def draw_pyramid(string, size):
if size > 15:
size = 15
if size < 5:
size = 5
length = size * 2 - 1
l = string * size
start = 0
end = 0
for stars in range(1, size + 1):
end += stars * 2 - 1
p = l[start:end]
start = end
print(p.center(length))
Output :
How many layers do you want it to be?: 10
t
hes
e***a
re***ju
st***rand
om***words*
these***are**
*just***random*
**words*these***a
re***just***random*
The way you are indexing l is wrong, based on what you want to achieve. If you study your desired output, you see that on the first row you want the substring l[0:1], on the second row l[1:4], then l[4:9], l[9:16] etc. The starting index is the sum of the first i odd elements, i.e. 1+3+5+.. and the stopping index is the sum of the first i+1 odd elements. Thus, at each step, you want l[i**2:(i+1)**2], with i starting at 0.
So your function should look like this
def draw_pyramid(string, size):
if size > 15:
size = 15
if size < 5:
size = 5
l = string * size
for i in range(size + 1):
p = l[i**2:(i+1)**2]
spaces = size - i
print(" " * spaces + p)
and it produces the desired output

Python program to give me numbers on the left with their sum on the right while having interchanged symbols in each line up to n (n=6)

Here's the picture of the program/ how it should work, it should display 1*1 then 12$3 < 3 is the sum of 1+2.. we only got to for loop.
I have tried a lot of solutions and this is what i got to at the end, for some reason i can't copy and paste it here without the code deleting whatever i had here..
also the output currently is:
please help and thanks a lot
I would implement this idea this way:
def func(n: int):
for i in range(1, n + 1):
nsum = 0 # Sum of numbers in nested loop.
last = 0 # Last number added to 'nsum'.
string = '' # Final string which is then printed.
for j in range(1, i + 1):
nsum += j # Add to total sum.
string += str(j) # Add to final string.
last = j # Set last number to current.
# Decide if either asterisk (*) or dollar ($) should be included
# in final message, after it append total sum.
string += ('*' if last % 2 else '$') + str(nsum)
print(string)
func(6)

How to get percentage of combinations computed?

I have this password generator, which comute combination with length of 2 to 6 characters from a list containing small letters, capital letters and numbers (without 0) - together 61 characters.
All I need is to show percentage (with a step of 5) of the combinations already created. I tried to compute all the combinations of selected length, from that number a boundary value (the 5 % step values) and count each combination written in text file and when when the count of combinations meets the boundary value, print the xxx % completed, but this code doesn't seem to work.
Do you know how to easily show the percentage please?
Sorry for my english, I'm not a native speaker.
Thank you all!
def pw_gen(characters, length):
"""generate all characters combinations with selected length and export them to a text file"""
# counting number of combinations according to a formula in documentation
k = length
n = len(characters) + k - 1
comb_numb = math.factorial(n)/(math.factorial(n-length)*math.factorial(length))
x = 0
# first value
percent = 5
# step of percent done to display
step = 5
# 'step' % of combinations
boundary_value = comb_numb/(100/step)
try:
# output text file
with open("password_combinations.txt", "a+") as f:
for p in itertools.product(characters, repeat=length):
combination = ''.join(p)
# write each combination and create a new line
f.write(combination + '\n')
x += 1
if boundary_value <= x <= comb_numb:
print("{} % complete".format(percent))
percent += step
boundary_value += comb_numb/(100/step)
elif x > comb_numb:
break
First of all - I think you are using incorrect formula for combinations because itertools.product creates variations with repetition, so the correct formula is n^k (n to power of k).
Also, you overcomplicated percentage calculation a little bit. I just modified your code to work as expected.
import math
import itertools
def pw_gen(characters, length):
"""generate all characters combinations with selected length and export them to a text file"""
k = length
n = len(characters)
comb_numb = n ** k
x = 0
next_percent = 5
percent_step = 5
with open("password_combinations.txt", "a+") as f:
for p in itertools.product(characters, repeat=length):
combination = ''.join(p)
# write each combination and create a new line
f.write(combination + '\n')
x += 1
percent = 100.0 * x / comb_numb
if percent >= next_percent:
print(f"{next_percent} % complete")
while next_percent < percent:
next_percent += percent_step
The tricky part is a while loop that makes sure that everything will work fine for very small sets (where one combination is more than step percentage of results).
Removed try:, since you are not handling any errors with expect.
Also removed elif:, this condition is never met anyway.
Besides, your formula for comb_numb is not the right one, since you're generating combinations with repetition. With those changes, your code is good.
import math, iterations, string
def pw_gen(characters, length):
"""generate all characters combinations with selected length and export them to a text file"""
# counting number of combinations according to a formula in documentation
comb_numb = len(characters) ** k
x = 0
# first value
percent = 5
# step of percent done to display
step = 5
# 'step' % of combinations
boundary_value = comb_numb/(100/step)
# output text file
with open("password_combinations.txt", "a+") as f:
for p in itertools.product(characters, repeat=length):
combination = ''.join(p)
# write each combination and create a new line
f.write(combination + '\n')
x += 1
if boundary_value <= x:
print("{} % complete".format(percent))
percent += step
boundary_value += comb_numb/(100/step)
pw_gen(string.ascii_letters, 4)

Finding a instances of a string inside a string

I'm working through the bioinformatics problems on rosalind.org and I've come across a problem where the python script I've written works on a smaller dataset but when applied to a larger one, I get the IndexError: list index out of range message.
Basically I have both a smaller motif and a larger DNA sequence and I have to find instances of the motif in the DNA sequence. When I put the sample dataset in the question into my script, it works fine and I get the right answer. However, using significantly larger motifs and sequences yields the previously mentioned error.
This is my code:
motif = "<motif around 9 characters>"
cMotif = list(motif)
motifLength = len(cMotif)
dna = "<DNA sequence around 900 characters>"
dnArray = list(dna)
locations = ""
position = 0
for nt in dnArray:
if (nt == cMotif[0]):
for x in range(0, (motifLength)):
if ((x + position) > len(dnArray)):
break
if (dnArray[position + x] == cMotif[x]):
if (x >= (motifLength - 1)):
locations += (str(position + 1) + " ")
break
else:
break
position += 1
print(locations)
The IndexError: list index out of range error occurs at line 18, if (dnArray[position + x] == cMotif[x]): hence I added the
if ((x + position) > len(dnArray)):
break
but this doesn't make a difference.
Cheers
Python's lists are zero-based, so when (x + position) == len(dnArray) trying to access dnArray[x + position] will be one past the last index. You should change your test to if (x + position) >= len(dnArray): to solve your problem.
I will suggest you to use python's regex instead for easiness.
import re
motif = "abc"
dna = "helloabcheyabckjlkjsabckjetc"
for i in re.finditer(motif,dna):
print(i.start(), i.end())
It gives you the start,end index in the string for every occrence of motif in dna
Here is your program that throws an error:
motif = "abcd"
cMotif = list(motif)
motifLength = len(cMotif)
dna = "I am a dna which has abcd in it.a"
dnArray = list(dna)
locations = ""
position = 0
for nt in dnArray:
if (nt == cMotif[0]):
for x in range(0, (motifLength)):
if ((x + position) > len(dnArray)):
break
if (dnArray[position + x] == cMotif[x]):
if (x >= (motifLength - 1)):
locations += (str(position + 1) + " ")
break
else:
break
position += 1
print(locations)
I changed if ((x + position) > len(dnArray)): to if ((x + position) >= len(dnArray)): and the error goes away because your program is never going to the break statement because you are not checking for the "=" condition. Remember, in programming languages things start from 0.
Put this line above your condition if ((x + position) > len(dnArray)): and you will know the reason:
print("My position is: " + str(x+position) + " and the length is: " + str(len(dnArray)))
The last line of this print statement will indicate that My position is: 33 and the length is: 33
See here that you have reached the end of the line and it does not match your existing criteria to go in the break statement.

Benford's law program

I have to write a program that proves Benford's Law for two Data lists. I think I have the code down for the most part but I think there are small errors that I am missing. I am sorry if this is not how the site is supposed to be used but I really need help. Here is my code.
def getData(fileName):
data = []
f = open(fileName,'r')
for line in f:
data.append(line)
f.close()
return data
def getLeadDigitCounts(data):
counts = [0,0,0,0,0,0,0,0,0]
for i in data:
pop = i[1]
digits = pop[0]
int(digits)
counts[digits-1] += 1
return counts
def showResults(counts):
percentage = 0
Sum = 0
num = 0
Total = 0
for i in counts:
Total += i
print"number of data points:",Sum
print
print"digit number percentage"
for i in counts:
Sum += i
percentage = counts[i]/float(Sum)
num = counts[i]
print"5%d 6%d %f"%(i,num,percentage)
def showLeadingDigits(digit,data):
print"Showing data with a leading",digit
for i in data:
if digit == i[i][1]:
print i
def processFile(name):
data = getData(name)
counts = getLeadDigitCounts(data)
showResults(counts)
digit = input('Enter leading digit: ')
showLeadingDigits(digit, data)
def main():
processFile('TexasCountyPop2010.txt')
processFile('MilesofTexasRoad.txt')
main()
Again sorry if this is not how I am supposed to use this site. Also, I can only use programming techniques that the professor has showed us so if you could just give me advice to clean up the code as it is I would really appreciate it.
Also, here are a few lines from my data.
Anderson County 58458
Andrews County 14786
Angelina County 86771
Aransas County 23158
Archer County 9054
Armstrong County 1901
Your error is coming from this line:
int(digits)
This doesn't actually do anything to digits. If you want to convert digits to an integer, you have to re-set the variable:
digits = int(digits)
Also, to properly parse your data, I would do something like this:
for line in data:
place, digits = line.rsplit(None, 1)
digits = int(digits)
counts[digits - 1] += 1
Lets walk though one cycle of your code and I think you'll see what the problem is. I'll be using this file here for data
An, 10, 22
In, 33, 44
Out, 3, 99
Now getData returns:
["An, 10, 22",
"In, 33, 44",
"Out, 3, 99"]
Now take a look the first pass though the loop:
for i in data:
# i = "An, 10, 22"
pop = i[1]
# pop = 'n', the second character of i
digits = pop[0]
# digits = 'n', the first character of pop
int(digits)
# Error here, but you probably wanted digits = int(digits)
counts[digits-1] += 1
Depending on how your data is structured, you need to figure out the logic to extract the digits you expect to get from your file. This logic might do better in the getData funciton, but it mostly depends on the specifics of your data.
Just to share here a different (and maybe more step-by-step) code. It's RUBY.
The thing is, Benford's Law doesn't apply when you have a specific range of random data to extract from. The maximum number of the data set that you are extracting random information from must be undetermined, or infinite.
In other words, say, you used a computer number generator that had a 'set' or specific range from which to extract the numbers, eg. 1-100. You would undoubtedly end up with a random dataset of numbers, yes, but the number 1 would appear as a first digit as often as the number 9 or any other number.
**The interesting** part, actually, happens when you let a computer (or nature) decide randomly, and on each instance, how large you want the random number to potentially be. Then you get a nice, bi-dimensional random dataset, that perfectly attains to Benford's Law. I have generated this RUBY code for you, which will neatly prove that, to our fascination as Mathematicians, Benford's Law works each and every single time!
Take a look at this bit of code I've put together for you!
It's a bit WET, but I'm sure it'll explain.
<-- RUBY CODE BELOW -->
dataset = []
999.times do
random = rand(999)
dataset << rand(random)
end
startwith1 = []
startwith2 = []
startwith3 = []
startwith4 = []
startwith5 = []
startwith6 = []
startwith7 = []
startwith8 = []
startwith9 = []
dataset.each do |element|
case element.to_s.split('')[0].to_i
when 1 then startwith1 << element
when 2 then startwith2 << element
when 3 then startwith3 << element
when 4 then startwith4 << element
when 5 then startwith5 << element
when 6 then startwith6 << element
when 7 then startwith7 << element
when 8 then startwith8 << element
when 9 then startwith9 << element
end
end
a = startwith1.length
b = startwith2.length
c = startwith3.length
d = startwith4.length
e = startwith5.length
f = startwith6.length
g = startwith7.length
h = startwith8.length
i = startwith9.length
sum = a + b + c + d + e + f + g + h + i
p "#{a} times first digit = 1; equating #{(a * 100) / sum}%"
p "#{b} times first digit = 2; equating #{(b * 100) / sum}%"
p "#{c} times first digit = 3; equating #{(c * 100) / sum}%"
p "#{d} times first digit = 4; equating #{(d * 100) / sum}%"
p "#{e} times first digit = 5; equating #{(e * 100) / sum}%"
p "#{f} times first digit = 6; equating #{(f * 100) / sum}%"
p "#{g} times first digit = 7; equating #{(g * 100) / sum}%"
p "#{h} times first digit = 8; equating #{(h * 100) / sum}%"
p "#{i} times first digit = 9; equating #{(i * 100) / sum}%"

Categories

Resources