I'm trying to create a very simple guitar tab creator in python, I had the idea but i'm not sure how to execute it the way I want. For example, I have a list containing each guitar string as a different item in the list, and I want the the user to be able to input which fret they want to use and which note. How can I replace a specific char in a list item based on a index number.
This is what I have so far:
tab = ['E|------------', 'B|------------', 'G|------------', 'D|------------', 'A|------------', 'E|------------']
for line in tab:
print(line)
fret = input("Fret: ")
note = input("Note: ")
#if note == 'E':
(Stuck here)
The output I'm looking for is something like:
e|-------5-7-----7-|-8-----8-2-----2-|-0---------0-----|-----------------|
B|-----5-----5-----|---5-------3-----|---1---1-----1---|-0-1-1-----------|
G|---5---------5---|-----5-------2---|-----2---------2-|-0-2-2---2-------|
D|-7-------6-------|-5-------4-------|-3---------------|-----------------|
A|-----------------|-----------------|-----------------|-2-0-0---0--/8-7-|
E|-----------------|-----------------|-----------------|-----------------|
I am aware that there is much more needed to get the output i'm looking for, but I want to try to figure that stuff out by myself first, I'm just looking for a nudge in the right direction to get a list item changed.
Note sure how you want to construct the whole thing, but here are some ideas:
The main line is
"-".join(str(d.get(idx, "-")) for idx in range(1, 9))
which, given a dict d having indices as keys and corresponding fret numbers as values, construct the string representation.
It uses the dict.get method which allows for a default value of "-" when nothing corresponds in the given dict.
from collections import namedtuple
def construct_string(indices, frets):
d = dict(zip(indices, frets))
out = "-".join(str(d.get(idx, "-")) for idx in range(1, 9))
return f"-{out}-"
String = namedtuple("Note", ["indices", "frets"])
strings = {
"e": String([4, 5, 8], [5, 7, 7]),
"B": String([3, 6], [5, 5]),
"G": String([2, 7], [5, 5]),
"D": String([1, 5], [7, 6]),
"A": String([], []),
"E": String([], []),
}
for string_name, string in strings.items():
string_line = construct_string(string.indices, string.frets)
print(f"{string_name}|{string_line}")
which prints:
e|-------5-7-----7-
B|-----5-----5-----
G|---5---------5---
D|-7-------6-------
A|-----------------
E|-----------------
Related
Imagine I have a dictionary as such:
barcodedict={"12_20":[10,15,20], "12_21":[5, "5_1","5_2",6]}
Then I have a number that corresponds to a date, lets say 12_21 and we append it to the values of this date if it is not there as such:
if 8 not in barcodedict["12_21"]:
barcodedict["12_21"].append(8)
{'12_20': [10, 15, 20], '12_21': [5, "5_1", "5_2", 6, 8]}
However, if this number is already present in the value list, I want to add it to the value list with an extra integer that states that its a new occurrence as such:
if 5 not in barcodedict["12_21"]:
barcodedict["12_21"].append(5)
else: #which is now the case
barcodedict["12_21"].append(5_(2+1))
Desired output:
{"12_20":[10,15,20], "12_21":[5, "5_1","5_2","5_3",6, 8]}
As can be seen from the second example, I am not allowed to put underscore in list numbers and they are removed (5_1 becomes 51). And how can I achieve adding a new listing with +1 to the last number? I tried iterating over them and then splitting them but this seems unpythonic and didn't work because the underscore is ignored.
Edit 7/19/2022 10:46AM,
I found a bit of a hackish way around but it seems to hold for now:
placeholder=[]
for i in barcodedict["12_21"]:
if "5" in str(i):
try:
placeholder.append(str(i).split("_")[1])
except:
print("this is for the first 5 occurence, that has no _notation")
print(placeholder)
if len(placeholder) == 0 :
placeholder=[0]
occurence=max(list(map(int, placeholder)))+1
barcodedict["12_21"].append("5_"+occurence)
prints {'12_20': [10, 15, 20], '12_21': [5, '5_1', '5_2', 6, '5_3']}
With the requested number/string mixture it can be done with:
if 5 not in barcodedict["12_21"]:
barcodedict["12_21"].append(5)
else: #which is now the case
i = 1
while True:
if f"5_{i}" not in barcodedict["12_21"]:
barcodedict["12_21"].append(f"5_{i}")
break
i += 1
Underscores used like that do not show up in print, because they are meant to be used for convenience in representing big numbers, but when interpreted they don't show like that. You should use string manipulation if the way they're are displayed matters, or the other way around if you want to actually use them as numbers and want simply to represent them in a convenient way.
Another solution:
def fancy_append(dct, key, val):
last_num = max(
(
int(s[1])
for v in dct[key]
if isinstance(v, str) and (s := v.split("_"))[0] == str(val)
),
default=0,
)
dct[key].append(f"{val}_{last_num+1}" if last_num > 0 else val)
barcodedict = {"12_20": [10, 15, 20], "12_21": [5, "5_1", "5_2", 6]}
fancy_append(barcodedict, "12_21", 5)
print(barcodedict)
Prints:
{'12_20': [10, 15, 20], '12_21': [5, '5_1', '5_2', 6, '5_3']}
So I have a list of strings such as this:
my_list=["---abcdefgh----abc--","--abcd-a--","----------abcdefghij----ab-","-abcdef---a-","----abcdefghijklm----abc--"]
I want, for each string, to retrieve the position where the first and last letters appear. Or in other words, to find the position of the first character that isn't a "-" and the position of the last character that isn't a "-". It would be perfect if I could save the result as two lists, one of the first positions and another for the last.
I've tried using find() at least for the first position but since the character I'm trying to find is one of several letters, I don't know how to do it.
The output I wanted was something like this:
first_positions=[3,2,10,1,4]
last_positions=[17,7,25,11,23]
Thanks in advance for any answer
Here is an implementation without using regex.
my_list=["---abcdefgh----abc--","--abcd-a--","----------abcdefghij----ab-","-abcdef---a-","----abcdefghijklm----abc--"]
def find_i(word):
first = None
last = None
for i, letter in enumerate(word):
if first == None:
if letter != '-':
first = i
else:
if letter != '-':
last = i
return (first, last)
r = list(map(find_i, my_list))
print(r) #I like this output more, but it is up to you.
first_positions = [i[0] for i in r]
last_positions = [i[1] for i in r]
print(first_positions)
print(last_positions)
Output:
[(3, 17), (2, 7), (10, 25), (1, 10), (4, 23)]
[3, 2, 10, 1, 4]
[17, 7, 25, 10, 23]
There is possibly a nicer way to do this, but one way to get it is to match all non-hyphen characters and get the start index of that match, and then to match all non-hyphen characters which are followed by 0 or more hyphens and then the end of the line, and get the start index of that match, and compile them into li
>>> import re
>>> [re.search(r'[^-]+', string).start() for string in my_list]
[3, 2, 10, 1, 4]
>>> [re.search(r'[^-]-*$', string).start() for string in my_list]
[17, 7, 25, 10, 23]
Check string is alphabet or not and then add index of string in the list. if you want to find first positions then by default function takes first then it returns the first indexes of string else it returns the last indexes
my_list=["---abcdefgh----abc--","--abcd-a--","----------abcdefghij----ab-","-abcdef---a-","----abcdefghijklm----abc--"]
def get_index(string,find='first'):
index_lt=[]
for idx,char in enumerate(string):
if char.isalpha():
index_lt.append(idx)
return index_lt[0] if find=='first' else index_lt[-1]
print([get_index(string) for string in my_list])
#[3, 2, 10, 1, 4]
print([get_index(string,find='last') for string in my_list])
#[17, 7, 25, 10, 23]
I want to reorder number members in a list (the list contains number only), and if string form of num1 + string form of num2 >= string form of num2 + string form of num1, then num1 should be ahead of num2 (I cannot compare numbers directly since a number may be very large, or the concatenated string format of a number could be very large and overflow). Here is an example,
num1 = 3
num2 = 30
since num1+num2 > num2+num1 #'330' > '303'
so, 3 should be ahead of 30
Another example, input is [3, 30, 34, 5, 9], and expected output is [9, 5, 34, 3, 30], and wondering how to write Python code elegantly? Could we write a customized cmp method for a Python list?
It seems this method not working? After sorted step, l is still the same as original value?
def cmp_values(v1, v2):
_v1 = int('{0}{1}'.format(v1, v2))
_v2 = int('{0}{1}'.format(v2, v1))
return cmp(_v2, _v1)
if __name__ == "__main__":
l = [3, 30, 34, 5, 9]
sorted(l, cmp=cmp_values)
print l
thanks in advance,
Lin
You can use a custom cmp method to sort the list:
def cmp_values(v1, v2):
_v1 = int('{0}{1}'.format(v1, v2))
_v2 = int('{0}{1}'.format(v2, v1))
return cmp(_v2, _v1)
and then use it to sort the list
In [5]: l = [3, 30, 34, 5, 9]
In [6]: sorted(l, cmp=cmp_values)
Out[6]: [9, 5, 34, 3, 30]
You do need to take care of the overflow issue though. In case the combination of v1, and v2 exceeds the int range.
Based on further comments from #LinMa
Using sorted wouldn't change the original list, so you need to assign the returned list to a new variable:
new_list = sorted(l, cmp=cmp_values)
Your question is very vague...
Next time, make sure to format your code properly using proper indentations (found by clicking Code below the 'Undo' arrow.
When it comes to sorting out a list, just use .sort() function, like so:
new_list = [3,6,1,2,4,5]
new_list.sort()
print(new_list)
This should return:
[1, 2, 3, 4, 5, 6]
This is the simplest explanation of how to sort it. Hope this helps a little.
Same idea as AKS. Longer code but maybe easy to follow steps.
list = [3, 30, 34, 5, 9, 8]
job_done = False
while(job_done == False):
job_done = True
for i in range(len(list) - 1):
as_is = int('{0}{1}'.format(list[i], list[i + 1]))
swaped = int('{0}{1}'.format(list[i + 1], list[i]))
if as_is < swaped:
tmp = list[i]
list[i] = list[i + 1]
list[i + 1] = tmp
job_done = False
print list
I am trying to learn what notes are where on the guitar, so I want to be able to type in what the string is tuned to and what fret I am playing and have the program tell me what note it is or type in the note and get back all the different places I can play it.
So far, I have a program that tells me what the note is based on the string and fret but I just wrote it the long way and it takes a lot of processing power. Based on what the user types in for what the string is tuned to, it opens a function for that string which asks what fret is being used, then based on the fret it runs one of the many elifs that I individually typed out.
For example:
elif fret == '3':
print('That note is E')
I know there's a way to do it with not nearly as much code, but I'm really new to programming clearly and can't quite come up with the logic.
Build a pair of dicts that map note names to pitch numbers and back, and you can build a simple function to do this, like:
NOTES = {"C" : 0, "C#" : 1, "D": 2, "D#" : 3, "E": 4, "F": 5,
"F#" : 6, "G": 7, "G#" : 8, "A": 9, "A#" : 10, "B": 11}
NAMES = dict([(v, k) for (k, v) in NOTES.items()])
def GetNote(stringNote, fretNum):
baseNote = NOTES[stringNote]
fretNoteNum = (baseNote + fretNum) % 12
return NAMES[fretNoteNum]
>>> GetNote("E", 0)
'E'
>>> GetNote("E", 1)
'F'
>>> GetNote("A", 7)
'E'
>>> GetNote("G", 6)
'C#'
The following is for Python 3.2.3.
I would like to write a function that takes two arguments, a key string and a target string. These function is to recursively determine (it must be recursive) the positions of the key string in the target string.
Currently, my code is as follows.
def posSubStringMatchRecursive(target,key):
import string
index=str.rfind(target, key)
if index !=-1:
print (index)
target=target[:(index+len(key)-1)]
posSubStringMatchRecursive(target,key)
The issue with this is that there is no way to store all the locations of the key string in the target string in a list as the numbers indicating the location will just be printed out.
So, my question is, is there any way to change the code such that the positions of the key string in the target string can be stored in a list?
Example Output
countSubStringMatchRecursive ('aatcgdaaaggraaa', 'aa')
13
12
7
6
0
Edit
The following code seems to work without the issue in Ashwini's code. Thanks, Lev.
def posSubStringMatchRecursive(target,key):
import string
index=str.rfind(target, key)
if index ==-1:
return []
else:
target=target[:(index+len(key)-1)]
return ([index] + posSubStringMatchRecursive(target,key))
def posSubStringMatchRecursive(target,key,res):
import string
index=str.rfind(target, key)
if index !=-1:
target=target[:(index+len(key)-1)]
res.append(index) #append the index to the list res,
return posSubStringMatchRecursive(target,key,res) #Use return here when calling recursively else your program will return None, and also pass res to the function
else:
return res
print(posSubStringMatchRecursive('aatcgdaaaggraaa', 'aa',[]))#pass a empty list to the function
print(posSubStringMatchRecursive('aatcgdaaaggraaa', 'a',[]))
output:`
[13, 12, 7, 6, 0]`
[14, 13, 12, 8, 7, 6, 1, 0]
Since it suspiciously resembles a homework question, here's an example of a recursive function that returns a list:
In [1]: def range_rec(limit):
if limit == 0:
return []
else:
return ([limit-1] + range_rec(limit-1)[::-1])[::-1]
...:
In [2]: range_rec(10)
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]