Python: Type Error unsupported operand type(s) for +: 'int' and 'str' - python-3.4

I'm really stuck, I am currently reading Python - How to automate the boring stuff and I am doing one of the practice projects.
Why is it flagging an error? I know it's to do with the item_total.
import sys
stuff = {'Arrows':'12',
'Gold Coins':'42',
'Rope':'1',
'Torches':'6',
'Dagger':'1', }
def displayInventory(inventory):
print("Inventory:")
item_total = sum(stuff.values())
for k, v in inventory.items():
print(v + ' ' + k)
a = sum(stuff.values())
print("Total number of items: " + item_total)
displayInventory(stuff)
error i get:
Traceback (most recent call last):
File "C:/Users/Lewis/Dropbox/Python/Function displayInventory p120 v2.py", line 17, in
displayInventory(stuff)
File "C:/Users/Lewis/Dropbox/Python/Function displayInventory p120 v2.py", line 11, in displayInventory
item_total = int(sum(stuff.values()))
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Your dictionary values are all strings:
stuff = {'Arrows':'12',
'Gold Coins':'42',
'Rope':'1',
'Torches':'6',
'Dagger':'1', }
yet you try to sum these strings:
item_total = sum(stuff.values())
sum() uses a starting value, an integer, of 0, so it is trying to use 0 + '12', and that's not a valid operation in Python:
>>> 0 + '12'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
You'll have to convert all your values to integers; either to begin with, or when summing:
item_total = sum(map(int, stuff.values()))
You don't really need those values to be strings, so the better solution is to make the values integers:
stuff = {
'Arrows': 12,
'Gold Coins': 42,
'Rope': 1,
'Torches': 6,
'Dagger': 1,
}
and then adjust your inventory loop to convert those to strings when printing:
for k, v in inventory.items():
print(v + ' ' + str(k))
or better still:
for item, value in inventory.items():
print('{:12s} {:2d}'.format(item, value))
to produce aligned numbers with string formatting.

You are trying to sum a bunch of strings, which won't work. You need to convert the strings to numbers before you try to sum them:
item_total = sum(map(int, stuff.values()))
Alternatively, declare your values as integers to begin with instead of strings.

This error produce because you was trying sum('12', '42', ..), so you need to convert every elm to int
item_total = sum(stuff.values())
By
item_total = sum([int(k) for k in stuff.values()])

The error lies in line
a = sum(stuff.values())
and
item_total = sum(stuff.values())
The value type in your dictionary is str and not int, remember that + is concatenation between strings and addition operator between integers. Find the code below, should solve the error, converting it into int array from a str array is done by mapping
import sys
stuff = {'Arrows':'12',
'Gold Coins':'42',
'Rope':'1',
'Torches':'6',
'Dagger':'1'}
def displayInventory(inventory):
print("Inventory:")
item_total = (stuff.values())
item_total = sum(map(int, item_total))
for k, v in inventory.items():
print(v + ' ' + k)
print("Total number of items: " + str(item_total))
displayInventory(stuff)

Related

How to count number of occurrences of a character in an array in Pascal

I have to script a pascal code that rations into calculation the frequency of a character's appearance in the code and displays it through the output mode
Input P2 changes:
Second Attempt at the coding phase
I tried revisioning the code.I added the output variable writeln('input array of characters'); & writeln('Number of Occurrences',k);, which should help me output how many times did the S character appear overall in the code, plus utilised the for & if commands to have the final values showcased based on the conditions, if the frequency is 1 then count in S, still getting errors, take a look at the Input P2 & Output P2
Input P1
function Count(t, s: String): Integer;
var
Offset, P: Integer;
begin
Result := 0;
Offset := 1;
P := PosEx(t, s, Offset);
while P > 0 do
begin
Inc(Result);
P := PosEx(t, s, P + 1);
end;
end;
Output P2
Target OS: Linux for x86-64
Compiling main.pas
main.pas(5,3) Error: Identifier not found "Result"
main.pas(7,8) Error: Identifier not found "PosEx"
main.pas(8,3) Error: Identifier not found "unsigned"
main.pas(8,12) Fatal: Syntax error, ";" expected but "identifier N" found
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
-------------------------------------------------------------------
Input P2
program p1
var S:string
i:integer
begin
writeln('input array of characters');
k:=O;
for i:=1 to length (S) do
if (S[i])='m') and (S[i+1]='a') then k:=k+1;
writeln('Number of Occurrences',k);
Readln;
end.
Output P2
Compiling main.pas
main.pas(2,1) Fatal: Syntax error, ";" expected but "VAR" found
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
The errors you see in the first block:
Identifier not found "Result"
Standard Pascal doesn't recognize the pseudovariable Result. In some Pascal implementations (like e.g. Delphi) it can be used to assign a value to the function result. The Pascal you are using needs to have the result of a function assigned to the name of the function. For example:
function Whatever(): integer;
begin
Whatever := 234;
end;
Identifier not found "PosEx"
Not all Pascal implementations include the PosEx() function. You need to use Pos() instead. But, the standard implementation of Pos() doesn't include the "search start position" that PosEx has. Therefore you need to ditch Pos() and do as you do in "Input P2", that is traverse the text character per character and count the occurances as you go.
Identifier not found "unsigned"
Seems you have removed that unknown identifier.
The error you see in the second block:
In Output P2 the error message should be clear. You are missing a semicolon where one is needed. Actually you are missing three of them.
You are also missing the line that reads user input: ReadLn(S);.
Finally, to calculate both upper and lower case characters you can use an extra string variable, say SU: string to which you assign SU := UpperCase(S) after reading user input, and then use that string to count the occurances.
I think this is more like what you want to do:
function Count(t, s: String): Integer;
var
Offset,Res, P: Integer;
begin
Res := 0
Offset := 1;
repeat
P := Pos(t, s, Offset);
if p>0 then
Inc(Res);
Offset := P+1
untl P = 0;
Count := Res;
end;
Now, if you don't have Pos, you can implement it:
Function Pos(const t,s:string; const Start:integer):Integer;
Var
LS, LT, {Length}
IxS, IxT, {Index)
R: Integer; {Result}
begin
R := 0;
{use only one of the two following lines of code}
{if your compiler has length}
LS := length(S); LT := Length(T);
{If it does not}
LS := Ord(s[0]); LT := Ord(T[0]);
if (LS <= LT) {if target is larger than search string, it's not there}
and (Start<=LT) and {same if starting position beyond size of S}
(Start+LT <-LS) then {same if search would go beyond size of S}
begin {Otherwise, start the search}
ixT := 1;
ixS := Start;
repeat
Inc(R); {or R:= R+1; if INC not available }
If (S[ixS] <> T[ixT]) then
R := 0 {they don't match, we're done}
else
begin {Move to next char}
Inc(ixS);
Inc(ixT);
end;
until (R=0) or (ixT>LT); {if search failed or end of target, done}
Pos := R;
end;

pyparsing parse c/cpp enums with values as user defined macros

I have a usecase where i need to match enums where values can be userdefined macros.
Example enum
typedef enum
{
VAL_1 = -1
VAL_2 = 0,
VAL_3 = 0x10,
VAL_4 = **TEST_ENUM_CUSTOM(1,2)**,
}MyENUM;
I am using the below code, if i don't use format as in VAL_4 it works. I need match format as in VAL_4 as well. I am new to pyparsing, any help is appeciated.
My code:
BRACE, RBRACE, EQ, COMMA = map(Suppress, "{}=,")
_enum = Suppress("enum")
identifier = Word(alphas, alphanums + "_")
integer = Word("-"+alphanums) **#I have tried to "_(,)" to this but is not matching.**
enumValue = Group(identifier("name") + Optional(EQ + integer("value")))
enumList = Group(enumValue + ZeroOrMore(COMMA + enumValue) + Optional(COMMA))
enum = _enum + Optional(identifier("enum")) + LBRACE + enumList("names") + RBRACE + Optional(identifier("typedef"))
enum.ignore(cppStyleComment)
enum.ignore(cStyleComment)
Thanks
-Purna
Just adding more characters to integer is just the wrong way to go. Even this expression:
integer = Word("-"+alphanums)
isn't super-great, since it would match "---", "xyz", "q--10-", and many other non-integer strings.
Better to define integer properly. You could do:
integer = Combine(Optional('-') + Word(nums))
but I've found that for these low-level expressions that occur many places in your parse string, a Regex is best:
integer = Regex(r"-?\d+") # Regex(r"-?[0-9]+") if you like more readable re's
Then define one for hex_integer also,
Then to add macros, we need a recursive expression, to handle the possibility of macros having arguments that are also macros.
So at this point, we should just stop writing code for a bit, and do some design. In parser development, this design usually looks like a BNF, where you describe your parser in a sort of pseudocode:
enum_expr ::= "typedef" "enum" [identifier]
"{"
enum_item_list
"}" [identifier] ";"
enum_item_list ::= enum_item ["," enum_item]... [","]
enum_item ::= identifier "=" enum_value
enum_value ::= integer | hex_integer | macro_expression
macro_expression ::= identifier "(" enum_value ["," enum_value]... ")"
Note the recursion of macro_expression: it is used in defining enum_value, but it includes enum_value as part of its own definition. In pyparsing, we use a Forward to set up this kind of recursion.
See how that BNF is implemented in the code below. I build on some of the items you posted, but the macro expression required some rework. The bottom line is "don't just keep adding characters to integer trying to get something to work."
LBRACE, RBRACE, EQ, COMMA, LPAR, RPAR, SEMI = map(Suppress, "{}=,();")
_typedef = Keyword("typedef").suppress()
_enum = Keyword("enum").suppress()
identifier = Word(alphas, alphanums + "_")
# define an enumValue expression that is recursive, so that enumValues
# that are macros can take parameters that are enumValues
enumValue = Forward()
# add more types as needed - parse action on hex_integer will do parse-time
# conversion to int
integer = Regex(r"-?\d+").addParseAction(lambda t: int(t[0]))
# or just use the signed_integer expression found in pyparsing_common
# integer = pyparsing_common.signed_integer
hex_integer = Regex(r"0x[0-9a-fA-F]+").addParseAction(lambda t: int(t[0], 16))
# a macro defined using enumValue for parameters
macro_expr = Group(identifier + LPAR + Group(delimitedList(enumValue)) + RPAR)
# use '<<=' operator to attach recursive definition to enumValue
enumValue <<= hex_integer | integer | macro_expr
# remaining enum expressions
enumItem = Group(identifier("name") + Optional(EQ + enumValue("value")))
enumList = Group(delimitedList(enumItem) + Optional(COMMA))
enum = (_typedef
+ _enum
+ Optional(identifier("enum"))
+ LBRACE
+ enumList("names")
+ RBRACE
+ Optional(identifier("typedef"))
+ SEMI
)
# this comment style includes cStyleComment too, so no need to
# ignore both
enum.ignore(cppStyleComment)
Try it out:
enum.runTests([
"""
typedef enum
{
VAL_1 = -1,
VAL_2 = 0,
VAL_3 = 0x10,
VAL_4 = TEST_ENUM_CUSTOM(1,2)
}MyENUM;
""",
])
runTests is for testing and debugging your parser during development. Use enum.parseString(some_enum_expression) or enum.searchString(some_c_header_file_text) to get the actual parse results.
Using the new railroad diagram feature in the upcoming pyparsing 3.0 release, here is a visual representation of this parser:

Need help understanding how gsub and tonumber are used to encode lua source code?

I'm new to LUA but figured out that gsub is a global substitution function and tonumber is a converter function. What I don't understand is how the two functions are used together to produce an encoded string.
I've already tried reading parts of PIL (Programming in Lua) and the reference manual but still, am a bit confused.
local L0_0, L1_1
function L0_0(A0_2)
return (A0_2:gsub("..", function(A0_3)
return string.char((tonumber(A0_3, 16) + 256 - 13 + 255999744) % 256)
end))
end
encodes = L0_0
L0_0 = gg
L0_0 = L0_0.toast
L1_1 = "__loading__\226\128\166"
L0_0(L1_1)
L0_0 = encodes
L1_1 = --"The Encoded String"
L0_0 = L0_0(L1_1)
L1_1 = load
L1_1 = L1_1(L0_0)
pcall(L1_1)
I removed the encoded string where I put the comment because of how long it was. If needed I can upload the encoded string as well.
gsub is being used to get 2 digit sections of A0_2. This means the string A0_3 is a 2 digit hexadecimal number but it is not in a number format so we cannot preform math on the value. A0_3 being a hex number can be inferred based on how tonubmer is used.
tonumber from Lua 5.1 Reference Manual:
Tries to convert its argument to a number. If the argument is already a number or a string convertible to a number, then tonumber returns this number; otherwise, it returns nil.
An optional argument specifies the base to interpret the numeral. The base may be any integer between 2 and 36, inclusive. In bases above 10, the letter 'A' (in either upper or lower case) represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. In base 10 (the default), the number can have a decimal part, as well as an optional exponent part (see ยง2.1). In other bases, only unsigned integers are accepted.
So tonumber(A0_3, 16) means we are expecting for A0_3 to be a base 16 number (hexadecimal).
Once we have the number value of A0_3 we do some math and finally convert it to a character.
function L0_0(A0_2)
return (A0_2:gsub("..", function(A0_3)
return string.char((tonumber(A0_3, 16) + 256 - 13 + 255999744) % 256)
end))
end
This block of code takes a string of hex digits and converts them into chars. tonumber is being used to allow for the manipulation of the values.
Here is an example of how this works with Hello World:
local str = "Hello World"
local hex_str = ''
for i = 1, #str do
hex_string = hex_string .. string.format("%x", str:byte(i,i))
end
function L0_0(A0_2)
return (A0_2:gsub("..", function(A0_3)
return string.char((tonumber(A0_3, 16) + 256 - 13 + 255999744) % 256)
end))
end
local encoded = L0_0(hex_str)
print(encoded)
Output
;X__bJbe_W
And taking it back to the orginal string:
function decode(A0_2)
return (A0_2:gsub("..", function(A0_3)
return string.char((tonumber(A0_3, 16) + 13) % 256)
end))
end
hex_string = ''
for i = 1, #encoded do
hex_string = hex_string .. string.format("%x", encoded:byte(i,i))
end
print(decode(hex_string))

How can I change ascii string to hex and vice versa in python 3.7?

I look some solution in this site but those not works in python 3.7.
So, I asked a new question.
Hex string of "the" is "746865"
I want to a solution to convert "the" to "746865" and "746865" to "the"
Given that your string contains ascii only (each char is in range 0-0xff), you can use the following snippet:
In [28]: s = '746865'
In [29]: import math
In [30]: int(s, base=16).to_bytes(math.ceil(len(s) / 2), byteorder='big').decode('ascii')
Out[30]: 'the'
Firstly you need to convert a string into integer with base of 16, then convert it to bytes (assuming 2 chars per byte) and then convert bytes back to string using decode
#!/usr/bin/python3
"""
Program name: txt_to_ASC.py
The program transfers
a string of letters -> the corresponding
string of hexadecimal ASCII-codes,
eg. the -> 746865
Only letters in [abc...xyzABC...XYZ] should be input.
"""
print("Transfer letters to hex ASCII-codes")
print("Input range is [abc...xyzABC...XYZ].")
print()
string = input("Input set of letters, eg. the: ")
print("hex ASCII-code: " + " "*15, end = "")
def str_to_hasc(x):
global glo
byt = bytes(x, 'utf-8')
bythex = byt.hex()
for b1 in bythex:
y = print(b1, end = "")
glo = str(y)
return glo
str_to_hasc(string)
If you have a byte string, then:
>>> import binascii
>>> binascii.hexlify(b'the')
b'746865'
If you have a Unicode string, you can encode it:
>>> s = 'the'
>>> binascii.hexlify(s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a bytes-like object is required, not 'str'
>>> binascii.hexlify(s.encode())
b'746865'
The result is a byte string, you can decode it to get a Unicode string:
>>> binascii.hexlify(s.encode()).decode()
'746865'
The reverse, of course, is:
>>> binascii.unhexlify(b'746865')
b'the'
#!/usr/bin/python3
"""
Program name: ASC_to_txt.py
The program's input is a string of hexadecimal digits.
The string is a bytes object, and each byte is supposed to be
the hex ASCII-code of a (capital or small) letter.
The program's output is the string of the corresponding letters.
Example
Input: 746865
First subresult: ['7','4','6','8','6','5']
Second subresult: ['0x74', '0x68', '0x65']
Third subresult: [116, 104, 101]
Final result: the
References
Contribution by alhelal to stackoverflow.com (20180901)
Contribution by QintenG to stackoverflow.com (20170104)
Mark Pilgrim, Dive into Python 3, section 4.6
"""
import string
print("The program converts a string of hex ASCII-codes")
print("into the corresponding string of letters.")
print("Input range is [41, 42, ..., 5a] U [61, 62, ..., 7a]. \n")
x = input("Input the hex ASCII-codes, eg. 746865: ")
result_1 = []
for i in range(0,len(x)//2):
for j in range(0,2):
result_1.extend(x[2*i+j])
# First subresult
lenres_1 = len(result_1)
result_2 = []
for i in range(0,len(result_1) - 1,2):
temp = ""
temp = temp + "0x" + result_1[i] #0, 2, 4
temp = temp + result_1[i + 1] #1, 3, 5
result_2.append(temp)
# Second subresult
result_3 = []
for i in range(0,len(result_2)):
result_3.append(int(result_2[i],16))
# Third subresult
by = bytes(result_3)
result_4 = by.decode('utf-8')
# Final result
print("Corresponding string of letters:" + " "*6, result_4, end = "\n")

Associate letters with its value and sort output in python

Please help on this. I have an input like this:
a = """A|9578
C|547
A|459
B|612
D|53
B|6345
A|957498
C|2910"""
I want to print in sorted way the numbers related with each letter like this:
A_0|459
A_1|957498
A_2|9578
C_0|2910
C_1|547
B_0|612
B_1|6345
D_0|53
So far I was able to store in array b the letters and numbers, but I'm stuck when I try to create dictionary-like array to join a single letter with its values, I get this error.
b = [i.split('|') for i in a.split('\n')]
c = dict()
d = [c[i].append(j) for i,j in b]
>>> d = [c[i].append(j) for i,j in b]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
TypeError: list indices must be integers or slices, not str
I'm working on python 3.6 just in case. Thanks in advance.
We'll split the string into pairs, sort those pairs, then use groupby and enumerate to come up with the indices.
from itertools import groupby
from operator import itemgetter
def process(a):
pairs = sorted(x.split('|') for x in a.split())
groups = groupby(pairs, key=itemgetter(0))
for _, g in groups:
for index, (letter, number) in enumerate(g):
yield '{}_{}|{}'.format(letter, index, number)
for i in process(a): print(i)
gives us
A_0|459
A_1|957498
A_2|9578
B_0|612
B_1|6345
C_0|2910
C_1|547
D_0|53

Resources