How to debug print a variable (name) and its value in Nim? - nim-lang

During quick and dirty debugging, I often use expressions like:
echo "variable1: ", variable1, " variable2: ", variable2
How can I leverage Nim's macro system to avoid repeating the variable name?

You can use a varargs macro that iterates over the arguments, and generates an AST which prints both the node's string literal as well as its value. Something like this:
import macros
macro debug*(n: varargs[typed]): untyped =
result = newNimNode(nnkStmtList, n)
for i in 0..n.len-1:
if n[i].kind == nnkStrLit:
# pure string literals are written directly
result.add(newCall("write", newIdentNode("stdout"), n[i]))
else:
# other expressions are written in <expression>: <value> syntax
result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
result.add(newCall("write", newIdentNode("stdout"), n[i]))
if i != n.len-1:
# separate by ", "
result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(", ")))
else:
# add newline
result.add(newCall("writeLine", newIdentNode("stdout"), newStrLitNode("")))
Example usage:
let x = 2
let y = 3
debug("hello", x, y, x*y)
Output:
hello, x: 1, y: 2, x * y: 6

Related

I want to compress each letter in a string with a specific length

I have the following string:
x = 'aaabbbbbaaaaaacccccbbbbbbbbbbbbbbb'. I want to get an output like this: abaacbbb, in which "a" will be compressed with a length of 3 and "b" will be compressed with a length of 5. I used the following function, but it removes all the adjacent duplicates and the output is: abacb :
def remove_dup(x):
if len(x) < 2:
return x
if x[0] != x[1]:
return x[0] + remove_dup(x[1:])
return remove_dup(x[1:])
x = 'aaabbbbbaaaaaacccccbbbbbbbbbbbbbbb'
print(remove_dup(x))
It would be wonderful if somebody could help me with this.
Thank you!
Unless this is a homework question with special constraints, this would be more conveniently and arguably more readably implemented with a regex substitution that replaces desired quantities of specific characters with a single instance of the captured character:
import re
def remove_dup(x):
return re.sub('(a){3}|([bc]){5}', r'\1\2', x)
x = 'aaabbbbbaaaaaacccccbbbbbbbbbbbbbbb'
print(remove_dup(x))
This outputs:
abaacbbb

how to detect a string in a variable

x = input("enter input: ")
if x == "hello":
print ("it does")
How would I detect if x has hello stored even if it has other charaters/strings?
This is as simple as using the in keyword.
x = "123hellomore"
if "hello" in x:
print("Hi there")
This only detects hello, if it is unobstructed so still in one word (not like "**hel*lo")
If entered input is single string then x below will be array of one element, if entered input is space separated strings (string of strings) then x will be array of multiple strings, below code handles both options
x = input("Enter input: ").split()
for y in x:
if y=="hello"
print("it does")

Unable to successfully compare two strings

phrase = input("enter the equation you want diferentiated:")#3x^2+2x^1+-4x^4
new_phrase = phrase.split("+")#splits phrase at the + operator
print(len(new_phrase))
for item in new_phrase:
c = (new_phrase>new_phrase.index("^"))#actul differentiation part c is the power of whatever (this is where python has a problem) line 6
y = (new_phrase<(new_phrase.index("^")-1))# y is the number before x
print(float(c)*float(y)+"^"+float(c)-1)# this is the final differentiated answer
#however it keeps saying ^ is not in the list how can I fix this?
Using Python 3.8.1
The actual main code is starting at for item. This is where the problem occurs, as the input is supposed to be 3x^2+2x^1+-4x^4, or something like, that but Python cannot seem to find where the power to sign "^" in the list thus the rest of the code from the " c =" does not work.
I have created a working version from your code. Mainly the problem was the type inconsistency. Furthermore I have added several comments to the code for the better understanding and it contains several prints for the debugging.
Code:
phrase = input("Enter the equation you want differentiated: ").lower() # 3x^2+2x^1+-4x^4
new_phrase = phrase.split("+") # splits phrase at the + operator
print("Elements: {}".format(new_phrase)) # Print elements of differential
for item in new_phrase:
print("Tested element: {}".format(item))
c = float(item.split("^")[-1]) # Get after part of "^" character
y = float(item.split("^")[0].replace("x", "")) # Get before part of "^" character (withour "x")
print("c={} ; y={}".format(c, y))
print(
"Result: {}^{}".format(float(c) * float(y), float(c) - 1)
) # this is the final differentiated answer
Output:
>>> python3 test.py
Enter the equation you want differentiated: 3x^2+2x^1+-4x^4
Elements: ['3x^2', '2x^1', '-4x^4']
Tested element: 3x^2
c=2.0 ; y=3.0
Result: 6.0^1.0
Tested element: 2x^1
c=1.0 ; y=2.0
Result: 2.0^0.0
Tested element: -4x^4
c=4.0 ; y=-4.0
Result: -16.0^3.0
Here is some Python script that can differentiate algebraic expressions based on your code.
phrase = input("enter the equation you want diferentiated:")#3x^2+2x^1+-4x^4
# Splits phrase at the + operator
split_phrase = phrase.split("+")
# Placeholder for the differentiated phrase
new_phrase = ""
for item in split_phrase:
# Exponent - index of ^ - 1
c = int(item[item.index("^") + 1:])
#Coefficient - from 0 to index of x - 1
y = int(item[0:item.index("x")])
#Reconstructs the algebraic expression
new_phrase += str(c*y) + "x^" + str(c-1)
# Adds a plus sign if it is not the last item
if split_phrase.index(item) != len(split_phrase) - 1:
new_phrase += "+"

python function call not printing as expected

So I have 2 functions - displayHand(hand) and calculateHandlen(hand)
def displayHand(hand):
"""
Displays the letters currently in the hand.
For example:
>>> displayHand({'a':1, 'x':2, 'l':3, 'e':1})
Should print out something like:
a x x l l l e
The order of the letters is unimportant.
hand: dictionary (string -> int)
"""
for letter in hand.keys():
for j in range(hand[letter]):
print(letter,end=" ")
print()
def calculateHandlen(hand):
"""
Returns the length (number of letters) in the current hand.
hand: dictionary (string-> int)
returns: integer
"""
handLen = 0
for i in hand:
handLen = handLen + hand.get(i,0)
return handLen
There's a loop in another function that is dependent on the above functions -
def playHand(hand, wordList, n):
"""
hand = dictionary
wordList = list of valid words
n = an integer passed while function call
"""
totalscore = 0
while(calculateHandlen(hand)>0):
print("Current Hand: " +str(displayHand(hand)))
newWord = input('Enter word, or a "." to indicate that you are finished: ')
Function call for playHand() is as follows:
wordList = loadWords() #loadWords could be a list of words
playHand({'n':1, 'e':1, 't':1, 'a':1, 'r':1, 'i':2}, wordList, 7)
I'm expecting the output to be:
Current Hand: n e t a r i i
Enter word, or a "." to indicate that you are finished:
However, it displays the following:
n e t a r i i
Current Hand: None
Enter word, or a "." to indicate that you are finished:
Don't know where I'm going wrong.
Note: I'm not allowed to make any changes to the first 2 functions.
displayHand() doesn't return anything, so the default None is returned. When you call it, it prints the output directly.
If you are not allowed to alter displayHand(), you need to print your label first, then call the function:
print("Current Hand: ", end='')
displayHand(hand)
The end='' removes the newline print() would normally write.

Trimming strings in Scala

How do I trim the starting and ending character of a string in Scala
For inputs such as ",hello" or "hello,", I need the output as "hello".
Is there is any built-in method to do this in Scala?
Try
val str = " foo "
str.trim
and have a look at the documentation. If you need to get rid of the , character, too, you could try something like:
str.stripPrefix(",").stripSuffix(",").trim
Another way to clean up the front-end of the string would be
val ignoreable = ", \t\r\n"
str.dropWhile(c => ignorable.indexOf(c) >= 0)
which would also take care of strings like ",,, ,,hello"
And for good measure, here's a tiny function, which does it all in one sweep from left to right through the string:
def stripAll(s: String, bad: String): String = {
#scala.annotation.tailrec def start(n: Int): String =
if (n == s.length) ""
else if (bad.indexOf(s.charAt(n)) < 0) end(n, s.length)
else start(1 + n)
#scala.annotation.tailrec def end(a: Int, n: Int): String =
if (n <= a) s.substring(a, n)
else if (bad.indexOf(s.charAt(n - 1)) < 0) s.substring(a, n)
else end(a, n - 1)
start(0)
}
Use like
stripAll(stringToCleanUp, charactersToRemove)
e.g.,
stripAll(" , , , hello , ,,,, ", " ,") => "hello"
To trim the start and ending character in a string, use a mix of drop and dropRight:
scala> " hello,".drop(1).dropRight(1)
res4: String = hello
The drop call removes the first character, dropRight removes the last. Note that this isn't "smart" like trim is. If you don't have any extra character at the start of "hello,", you will trim it to "ello". If you need something more complicated, regex replacement is probably the answer.
If you want to trim only commas and might have more than one on either end, you could do this:
str.dropWhile(_ == ',').reverse.dropWhile(_ == ',').reverse
The use of reverse here is because there is no dropRightWhile.
If you're looking at a single possible comma, stripPrefix and stripSuffix are the way to go, as indicated by Dirk.
Given you only want to trim off invalid characters from the prefix and the suffix of a given string (not scan through the entire string), here's a tiny trimPrefixSuffixChars function to quickly perform the desired effect:
def trimPrefixSuffixChars(
string: String
, invalidCharsFunction: (Char) => Boolean = (c) => c == ' '
): String =
if (string.nonEmpty)
string
.dropWhile(char => invalidCharsFunction(char)) //trim prefix
.reverse
.dropWhile(char => invalidCharsFunction(char)) //trim suffix
.reverse
else
string
This function provides a default for the invalidCharsFunction defining only the space (" ") character as invalid. Here's what the conversion would look like for the following input strings:
trimPrefixSuffixChars(" Tx ") //returns "Tx"
trimPrefixSuffixChars(" . Tx . ") //returns ". Tx ."
trimPrefixSuffixChars(" T x ") //returns "T x"
trimPrefixSuffixChars(" . T x . ") //returns ". T x ."
If you have you would prefer to specify your own invalidCharsFunction function, then pass it in the call like so:
trimPrefixSuffixChars(",Tx. ", (c) => !c.isLetterOrDigit) //returns "Tx"
trimPrefixSuffixChars(" ! Tx # ", (c) => !c.isLetterOrDigit) //returns "Tx"
trimPrefixSuffixChars(",T x. ", (c) => !c.isLetterOrDigit) //returns "T x"
trimPrefixSuffixChars(" ! T x # ", (c) => !c.isLetterOrDigit) //returns "T x"
This attempts to simplify a number of the example solutions provided in other answers.
Someone requested a regex-version, which would be something like this:
val result = " , ,, hello, ,,".replaceAll("""[,\s]+(|.*[^,\s])[,\s]+""", "'$1'")
Result is: result: String = hello
The drawback with regexes (not just in this case, but always), is that it is quite hard to read for someone who is not already intimately familiar with the syntax. The code is nice and concise, though.
Another tailrec function:
def trim(s: String, char: Char): String = {
if (s.stripSuffix(char.toString).stripPrefix(char.toString) == s)
{
s
} else
{
trim(s.stripSuffix(char.toString).stripPrefix(char.toString), char)
}
}
scala> trim(",hello",',')
res12: String = hello
scala> trim(",hello,,,,",',')
res13: String = hello

Resources