Why is this a Concatenation Error? Just Can't Figure It Out - concatenation

My code is here: https://pastebin.com/UxZibL4B
This simple gaming program is what I am using to learn to code. It will, eventually, manage all of the tasks for an old school version of dungeons and dragons. I'd like it to be able to handle all of the referee functions for the game.
Here is the offending line:
Palanquin_v = ['ATTRIBUTES ', '^ ', 0, 'S ', 0, 'F ', 0, 'C ', 1, 'U ', 0, 'X ', 0, '£ ', 0, 'T ', 0, 'ARMOR CLASS ', 12, 'HIT DICE ', 3, 'D8', 1, 'D6', 0, 'D4', 0, 'D10', 0, 'D12', 0, 'DAMAGE ', '1d8', 0, 0, 0, 0, 'SPECIAL ', 'Roll encounter each turn, which aids palanquin if given 1,000 GP. Buys gems at 2d6 x 10% value; insulted if refused.', 'MOVE ', 12, 'FLIGHT ', 0, 'SWIM ', 0, 'Palanquin'] # got a traceback to here, traceback was 288, then 240 and variable printed was Monster_Generator_Roll_v, with a value of 89
For now, all it does is "roll up" random monster encounters from a specified list. Each of the monsters is given a number of stats (most of which are presently incomprehensible, I'm trying to get it to work before I pretty-it-up).
However, there are two "rolls" that can modify the stats of the monsters:
A monster can be "Sorcerous" meaning the it knows how to cast spells, which are also generated randomly from a list.
A monster can also be "Tremendous" meaning it is just bigger and meaner than most monsters of its type. When this result is generated, the creature's armor class, hit dice and damage per attack (across multiple attacks, if it can make more than one) are all increased by +4.
Any monster can, again, randomly, get multiple additions of both the "Sorcerous" and "Tremendous" results. Thus, a "Sorcerous, Sorcerous, Tremendous, Tremendous,Tremendous, Vampire" (extremely uncommon, but it could occur) would get the additional "Sorcerous" increase twice, and the "Tremendous", increase three times.
By and large it works pretty well, but it is giving me a concatenation error (can only concatenate int to int, not int to string) when it hits line number 89, which contains the stats for the Palanquin monster.
Though this is a laid out exactly like every other line of code, for some reason, the concatenation error arises only when the "Tremendous" roll takes place. When python tries to give the numeric +4 boost to the monster's armor class, it tells me that I am trying to concatenate an integer to a string.
I don't understand this, as it looks like a string in the code, every other monster armor class is treated the same way, and notepad++ is displaying the stat in red, which is what it does for integers on my computer.
Like a good little programmer, I've been going over this for days, looking it up on stack overflow, youtube, reddit, etc., and just can't figure it out.
I'm sure its something simple.
Any help?
Thanks.
BTW: I'm brand new to programming, and to stackoverflow, and I'm sure I'm breaking a dozen rules, but none intentionally. Your patience is appreciated.
PS The code is in a loop simply because it was easier for me to try to debug if it broke quickly. Again, I hope I'm not breaking any rules.

By adding a print statement just before the addition, I see a **:
103
Tremendous
89
Black Knight
>>>>> ** 4
Traceback (most recent call last):
File "DnD.py", line 295, in <module>
Add_Tremendous_To_Random_Monster_f()
File "DnD.py", line 247, in Add_Tremendous_To_Random_Monster_f
Tremendous_Monster_ARMOR_CLASS_v = (Randomly_Generated_Monster_v[18] + (Tremendous_Monster_Bonus_v))
TypeError: can only concatenate str (not "int") to str
If I check the Black Knight (line 163), I see:
'ARMOR CLASS ','**'
The concatenate fails because of the **. It is expecting a number.

Related

Why does printing more than 2 values from this array cause an error?

Why does my code return an ArgumentError when printing more than 2 values from my array?
Code:
gamestate = Array['1','2','3','4','5','6','7','8','9']
player = 'X' #x is the first player#
turns = 0 # number of turns that have passed
puts "TICTACTOE"#prints initial screen{#
puts gamestate[0,1,2]
puts gamestate[3,4,5]
puts gamestate[6,7,8]
Error:
Traceback (most recent call last):
1: from C:/Users/Hunter/Desktop/programming/rubyprograms/Basics/tictactoe.rb:5:in `<main>'
C:/Users/Hunter/Desktop/programming/rubyprograms/Basics/tictactoe.rb:5:in `[]': wrong number of arguments (given 3, expected 1..2) (ArgumentError)
<hr>
Why does my code return an ArgumentError when printing more than 2 values from my array?
As the error message clearly says:
Traceback (most recent call last):
1: from C:/Users/Hunter/Desktop/programming/rubyprograms/Basics/tictactoe.rb:5:in `<main>'
C:/Users/Hunter/Desktop/programming/rubyprograms/Basics/tictactoe.rb:5:in `[]': wrong number of arguments (given 3, expected 1..2) (ArgumentError)
The error message gives error details, including a stack trace showing at what point in the execution the error occurred, and a filename and linenumber showing at what point in the source code the error occurred, but also an informational message:
wrong number of arguments (given 3, expected 1..2)
So, you passed three arguments to the method [] which however only accepts one or two arguments, as we can also clearly see in the documentation of Array#[]:
array[index] → object or nil
array[start, length] → object or nil
array[range] → object or nil
array[aseq] → object or nil
As you can see, there are four different ways that we can call the [] method:
with one Integer (or any object implicitly convertible to Integer) argument denoting the index of the object we want to retrieve,
with two Integer arguments, denoting the start index and the length of the subarray we want to retrieve,
with one Range argument, denoting the start and the end index of the subarray we want to retrieve, and
with one Enumerator::ArithmeticSequence argument, denoting the sequence of indices of the elements you want to retrieve.
While those are many different options, none take three arguments.
Since it looks like you always want exactly three consecutive elements starting from some specific index, you can use the second form here, which takes the starting index and the length of the subarray as arguments:
puts gamestate[0, 3]
puts gamestate[3, 3]
puts gamestate[6, 3]
If you wanted to retrieve multiple elements at arbitrary, non-consecutive indices instead, you could use Array#values_at instead.
By the way, there are a couple of non-idiomatic bits in your code:
Your style is inconsistent. You are sometimes using single quotes and sometimes using double quotes for no discernible reason. When there are two different ways to express something, and you are using those two different ways, people will assume that you want to express an important difference by using those two different styles. However, in this case, there doesn't seem to be any difference. It is generally preferred to always use single quotes unless you want to use string interpolation or need a particular escape sequence, or the string contains a single quote:
puts 'TICTACTOE'
There should be a space after a comma:
gamestate = Array['1', '2', '3', '4', '5', '6', '7', '8', '9']
and
puts gamestate[0, 1, 2]
puts gamestate[3, 4, 5]
puts gamestate[6, 7, 8]
There is no need to use the Array::[] method here, you can just the normal Array literal syntax instead:
gamestate = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
Even better, you could use a %w percent string literal:
gamestate = %w[1 2 3 4 5 6 7 8 9]
Alternatively, you could also use a Range and convert it to an Array:
gamestate = ('1'..'9').to_a
Since it looks like you are modeling a Tic Tat Toe game board with three rows of three cells each, a linear Array might not be the best possible way of representing it. A nested Array is probably easier to work with:
gamestate = [
%w[1 2 3],
%w[4 5 6],
%w[7 8 9]
]
The best representation, though, would be to represent your game state object as, you know, a GameState object, because that's what it is: a game state is a game state, not an array-of-strings, or an array-of-arrays-of-string. Ruby is an object-oriented language, after all, not an array-of-strings-oriented language.

State Diagram for Turing Machine to compute next string in lexicographical order

What would the state diagram look like for a Turing Machine that computes the next string in lexicographical order over alphabet Σ = {1, 2, 3}?
String size is 4, i.e ---1, ---2, ---3, --11, --12, etc...
Already tried figuring it out from Michael Sipser's Introduction to Theory of Computation with no luck.
Also tried to look it up online, again with no luck.
Thanks in advance!
If I have understood correctly, you want a TM to take as input a string over {1, 2, 3} of length up to four, and to overwrite this number with the string over the same alphabet which comes next in lexicographic order. Here is a strategy for this problem.
move right three times so we're looking at the fourth symbol on the tape.
if this is blank, our input is malformed and we die. otherwise, if the symbol is 1, write 2 and halt-accept; if 1, write 2 and halt-accept; if 3, write 1 and move left in state "carry2"
if this is blank, 1 or 2, write 1, 2 or 3, respectively, and halt-accept. if 3, write 1 and move left in state "carry3"
if this is blank, 1 or 2, write 1, 2 or 3, respectively, and halt-accept. if 3, write 1 and move left in state "carry4"
if this is blank, 1 or 2, write 1, 2 or 3, respectively, and halt-accept. if 3, the input was the number 3333 and there is no lexicographically larger 4-digit string over {1, 2, 3}… so either crash or wrap and write ---1 to the tape.
Note that this does not verify the tape contents are sane... since we are using blanks to encode "missing" high-order digits we can just reasonably assume there's nothing after position 4 on the tape (defining what our TM does carefully to avoid implying we did anything after there). Furthermore, we are not sanitizing the front, so mixing symbols and blanks improperly could be an issue... so we could either run some steps first to validate the input or just require the input be well-formed when we get it.

The code for a calculator I made doesn't act like I thought it would? (Python 3.x)

I'm actively learning Python at the moment. I've already had some experience with code, but not nearly enough that I would call myself a good coder (or even a competent one tbh).
I tried to create a (pretty) simple calculator script. I wanted to make sure the user could choose how many different values (s)he wanted to calculate together. To do that I created a while loop.
uArray = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
def divide():
uAmount = int(input("How many different values do you want to add together? (max 10) "))
if uAmount <= 10:
for amount in range(0, uAmount):
uArray[amount] = int(input("enter a number: "))
else:
print("ERROR\nMax 10 different values supported")
return 1
global uTotal
uTotal = 1
for amount1 in range(0, (uAmount - 1)):
uTotal /= uArray[amount1]
print("The result is: " + str(uTotal))
I know this code might look REAL ugly to a lot af you and I'm sure that the same process could be done way easier and simpler if I knew how.
I just can't figure out why my current method doesn't work, even after trying to google it.
EXAMPLE: If I choose to use 2 different values. And I make those values 50 and 2, it should give 25 of course. But it gives 0.02 instead.
Thanks in advance to anyone willing to help! (and sorry if this is a noob question ahaha)
I just can't figure out why my current method doesn't work
Simple. You start with uTotal equal to 1. Then you divide by each of your numbers (except the last). Since you only have two numbers, 50 and 2 and you don't use the second one (due to range(0, uAmount - 1)), the whole calculation equals to this:
1 / 50 # => 0.02
How to fix?
Instead of setting uTotal to 1, set it to the value of the first element. Then apply your operation (division, in this case), using all other elements (except the first).
Array unpacking syntax may come in handy here:
total, *rest = uArray
for operand in rest:
total /= operand
Currently it's taking 1 and dividing it by your first input, which is 50.
Note that the for loop won't iterate like you were thinking. Need to remove the '- 1'
Here's a version:
uArray = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
def divide():
uAmount = int(input("How many different values do you want to add together? (max 10) "))
if uAmount <= 10:
for amount in range(0, uAmount):
uArray[amount] = int(input("enter a number: "))
else:
print("ERROR\nMax 10 different values supported")
return 1
global uTotal
uTotal = uArray[0]
for amount1 in range(1, (uAmount)):
uTotal /= uArray[amount1]
print("The result is: " + str(uTotal))

Filter data using histogram in C

I have 25 values from a sensor between 0 and 40.
Most values will be around the true real value but some can be far away.
How can I get a reliable measure based on the values?
Mean will not work as lower or higher values will blow up the average.
Lets suppose we have these values:
10, 13, 22, 21, 19, 18, 20, 21, 22, 21, 19, 30, 30, 21, 20, 21, 22, 19, 18, 20, 22, 21, 10, 18, 19
I think best approach will be using histogram. Defining manual ranges will fail as we can reject some good values next to range bounds.
Automatic ranges calculated from the incoming data wont work because they can overlap each other.
I am coding over Arduino so memory allocation will not be the best idea.
May be a moving average will be a nice choice, define the length say d then at any instant your filtered value will be the average of the previous d sensor values.
If you really concern about deleting some strange values, you may set a threshold in addition to your moving average, but i don't recommend it, i guess you have to observe the real pattern your sensor is following.
P.S: My answer could be opinion-based, but this is the way i deal with sensors [in my work] and this is working perfectly for the company up to now.
Maybe calculating the Trimmed Mean of these values could help you, or just
the median.
How to calculate the truncated or trimmed mean?
The filter I have ended used is a multiple mean.
I process the mean of all values, then discard those values over a threshold from the first mean and then I compute the mean of the left values.
If you're actually after an average, this won't work for you, but this method requires no extra memory to manage a buffer of samples:
void loop() {
static float mean = analogRead(A0);
int newInput = analogRead(A0);
mean = (mean * 0.95) + (newInput * 0.05);
Serial.println(mean);
}
You can adjust the constants (0.95 and 0.05) to whatever you like, as long as they add up to 1. The smaller the multiplier of mean, the faster mean will track new values.
If you don't like the overhead of floating point math, the same idea works quite well in fixed point.

How can I break up a list in prolog, given a pivot?

I'm working on a small project to lean prolog. What I'm trying to do right now is, given a sentence, return a list of words. So, I'm taking in a character array, e.g. "highs and lows", and trying to split it up into "highs" "and" "lows". I'm using a character array because I want to play with the words themselves, and I don't think strings work for that.
Here's my code.
get_first_word([], _, []):-
!.
get_first_word(X, Pivot, Input):-
append(X, [Pivot|_], Input),
!.
split_at([],_).
split_at(Input, Pivot):-
get_first_word(X, Pivot, Input),
writef(X),
append(X, Y, Input),
split_at(Y, Pivot).
The problem I'm getting is that this turns into an infinite loop. Eventually it'll pass itself empty input, and my base case isn't well-written enough to handle this. How do I fix this?
I think that get_first_word misses an argument: it should 'return' both the word and the rest, accounting for the possibility that Pivot doesn't appear in input.
I've also moved arguments to follow the conventional 'input at begin, output at end'.
get_first_word(Input, Pivot, Word, Rest):-
append(Word, [Pivot|Rest], Input), !.
get_first_word(Input, _Pivot, Input, []).
split_at([], _).
split_at(Input, Pivot):-
get_first_word(Input, Pivot, W, Rest),
writef(W),nl,
split_at(Rest, Pivot).
test:
?- split_at("highs and lows", 0' ).
highs
and
lows
true .
If you use SWI-Prolog, it is worth considering using atoms to represent sentences, words, parts of words and so on. As you can see here, you problem becomes (if your sentence is an atom):
?- atomic_list_concat(Ws, ' ', 'highs and lows').
Ws = [highs, and, lows].
There are further useful predicates, for example atom_concat/3 (we can say it is append/3 for atoms), or sub_atom/5 which can be useful in multiple ways.
As a side note, SWI-Prolog has no artificial limit on the length of atoms and actually recommends using atoms instead of strings or character code lists.
When describing lists (in this case: lists of character codes, which is what your strings are), always also consider using DCGs. For example:
string_pivot_tokens(Cs, P, Ts) :- phrase(tokens(Cs, P, []), Ts).
tokens([], _, Ts) --> token(Ts).
tokens([C|Cs], P, Ts) -->
( { C == P } -> token(Ts), tokens(Cs, P, [])
; tokens(Cs, P, [C|Ts])
).
token([]) --> [].
token([T|Ts]) --> { reverse([T|Ts], Token) }, [Token].
Example:
?- string_pivot_tokens("highs and lows", 0' , Ts), maplist(atom_codes, As, Ts).
Ts = [[104, 105, 103, 104, 115], [97, 110, 100], [108, 111, 119, 115]],
As = [highs, and, lows] ;
false.

Resources