User input manipulation - python-3.9

Please I'm in need of a lift right now. I want the user to be able to have the option of re-entering his numerical input if perhaps, he/she entered an alphabet by mistake.
Right now it just loops infinitely on the "Please select a valid option" and "Try again" outputs.
print("\n-----Factorial Calculator------\n")
def option():
opt = (input('Try again? y/n: '))
if option == 'y':
facto(num)
elif option == 'n':
exit()
else:
print("Please select a valid option")
option()
def facto(factorial):
fact = 1
for nums in range(1, num+1):
fact = fact * nums
return fact
try:
num = int(input("Number(Just input the number): "))
except ValueError:
print("Invalid input")
option()
print(f" {num}! = {facto(num)}")

First, rather than calling option recursively, simply put a loop inside it.
Second, when the user enters y into the "Try again?" input, it should not calculate the factorial there, but return the user back to the original input, by breaking out of the loop within the option call.
Putting these two together will fix option:
def option():
while True:
retry = input('Try again? y/n: ')
if retry == 'y':
break
elif retry == 'n':
exit()
else:
print("Please select a valid option")
Third, you need some kind of loop around your initial input, otherwise how will they enter the number again after indicating they want to try again?
Fix this by sticking the initial num assignment and option call in a while loop, with the same try; except statement you had before:
while True:
try:
num = int(input("Number(Just input the number): "))
break
except ValueError:
print("Invalid input")
option()
continue

I see someone else got an answer in ahead of me which identified the bug in option() and the bug which prevents user re-entering the number but I'll post this anyway because there are other ways your code can be restructured.
print("\n-----Factorial Calculator------\n")
# Each function should handle just one thing
# Eg, option() should just handle whether user wants to continue, not try to handle factorial calc
# Also it's best to let the mainline logic decide whether to exit() or not
# This function should just return 'y' or 'n'
# Note that the original code captured the user's option in variable `opt` but then checked variable `option`.
# That's why it looped endlessly
def option():
opt = ' '
while ( opt != 'y' and opt != 'n' ):
opt = (input('Try again? y/n: '))
if opt == 'y':
return opt
elif opt == 'n':
return opt
else:
print("Please select a valid option")
# You specified argument `factorial` in original code but then did not use it.
# It still worked because the variable `num` was defined at the top level in the mainline
# Functions should be self-contained and rely only on the arguments that are passed into them
def facto(n):
fact = 1
for nums in range(1, n+1):
fact = fact * nums
return fact
opt = 'y'
is_print = False
while ( opt == 'y' ):
try:
num = int(input("Number(Just input the number): "))
opt = 'n'
is_print = True
except ValueError:
print("Invalid input")
opt = option()
if ( is_print ):
print(f" {num}! = {facto(num)}")

Thanks everyone for the help, but after struggling with it for a couple of days and taking few days off due to illness, I somehow did it. Eureka!
def facto(n):
fact = 1
for i in range(1, n + 1):
fact = fact * i
return fact
def opt():
option = (input("Do you want to try again? y/n: "))
if option == 'y':
number()
elif option == 'n':
exit()
else:
print("\nPlease select a valid option.")
opt()
def number():
try:
num = int(input("Number: "))
print(f"{num}! = {facto(num)}")
except ValueError:
print("Invalid input! Please input integers only")
opt()
number()

Related

Messages repeating infinitely -- Discord.py

So this is 100% a wip and I'm super confused on how to stop the discord bot from reading the same user message over and over again.
import discord
class MyClient(discord.Client):
async def on_ready(self):
print('Logged in as')
print(self.user.name)
print(self.user.id)
print('------')
async def on_message(self, message):
global choice
global r
# we do not want the bot to reply to itself
if message.author.id == self.user.id:
return
if message.content.startswith('!hello'):
await message.reply('Hello!', mention_author=True)
r=0
basic = True
#upgrade1 = False
choice = '!idle'
while(choice != '!end'):
if message.content.startswith('!idle'):
choice= await message.reply('!click / !bank / !upgrade / !minigame / !end')
if message.author.id == self.user.id:
return
if message.content.startswith('!click' or '!c'):
r = r + 1
await message.reply("You have " + str(r) + " Renown")
elif message.content.startswith ('!bank'):
await message.reply ("You have " + str(r) + " Renown")
#elif message.content.startswith ('!upgrade' and r >= 10):
#await message.reply('Upgrading..')
#r = r - 10
#basic = False
#elif message.content.startswith ('!upgrade' and r < 10):
#await message.reply ('Not Enough Renown')
elif message.content.startswith('!minigame' or '!mg'):
#random number choosing game
await message.reply ("Game")
elif message.content.startswith ('!end'):
basic = False
#while time.time() < future:
#r =r + .00001
client = MyClient()
client.run
Your issue comes from the while(choice != '!end') loop. Once the bot enters that loop, the messages he is sending within that loop of course will be repeated because you are not changing the value of choice unless the message is !idle.
Notice in your code how if the command is for example !click, you are sending the following message:
await message.reply("You have " + str(r) + " Renown")
But you are not changing the value of choice, so in the next iteration of the while loop it will repeat the same, once and again.
I'm not sure what you are trying to achieve, but having a while loop in the on_message event does not seem a good idea for me, as this is a blocking feature. In my opinion you should replace it with an if.

Golang switch statement only calls function once

I encountered a rather strange bug writing a program in Go.
Essentially, I have a switch statement where each case is supposed to call a function, setill, twice. But when the relevant case runs, it only calls the function once.
Here's the code snippet:
check := true
n, e, s, w := b.North, b.East, b.South, b.West
switch {
// NE (>)
case n.Closed && e.Closed:
check = check && p.setIll(s)
check = check && p.setIll(w)
// NS (\\)
case n.Closed && s.Closed:
check = check && p.setIll(e)
check = check && p.setIll(w)
// NW (^)
case n.Closed && w.Closed:
check = check && p.setIll(e)
check = check && p.setIll(s)
// ES (v)
case e.Closed && s.Closed:
check = check && p.setIll(n)
check = check && p.setIll(w)
// EW (//)
case e.Closed && w.Closed:
fmt.Println("Running setIll the first time")
check = check && p.setIll(n)
fmt.Println("Running it again")
check = check && p.setIll(s)
fmt.Println("And now we're done running")
// SW (<)
case s.Closed && w.Closed:
check = check && p.setIll(n)
check = check && p.setIll(e)
}
Here's setIll:
func (p Player) setIll(n *Node) bool {
fmt.Println("I'm running!")
p.Illegal.Nodes[n.Loc.X][n.Loc.Y].Closed = true
return !p.Forced.Nodes[n.Loc.X][n.Loc.Y].Closed
}
This produces the following output:
Running setIll the first time
I'm running!
Running it again
And now we're done running
Notice that "I'm running!" only appears once in the output. Any idea why this may be?
It's not the switch tripping you up, it's how && works.
&& and || are short-circuiting operators: they don't execute what's on the right-hand side at all if the left-hand result is enough to determine what the answer will be. If your expression were a && f() and a were false it's not necessary to run f() to see that the end result will be false too. The way the Go spec puts this is "The right operand is evaluated conditionally."
This is common across a lot of languages. It's helpful when your first check has to pass for it to make sense to run the others. For example, say you want to check user permissions in a Web app, but only if a user is logged in at all (user != nil): user != nil && user.HasPermission(requiredPerm) does what you need.
If you want to set the check var the same way you're doing it now, but with setIll always called twice, you can assign the setIll results to variables outside of any && expression:
ck1, ck2 := p.setIll(n), p.setIll(s)
check = check && ck1 && ck2

How to restart this program

So this is my code that works fine alone.....
def program():
for x in y:
for g in t:
if x == g:
return True
return False
print ("Welcome")
y = input(" enter...").lower().split()
with open("pro.txt", "r")as file:
lines = file.readlines()
o = False
for line in lines:
item = line.split("-")
t = item[0].split()
a = item[1]
if program():
print (a)
o = True
if o == False:
print ("sorry")
I did ask this question before, but I didn't explain well enough. so the problem I have here is that I do not know how to restart this program one of my attempts was this.....
def restart():
answer = ''
while answer not in ('y','n'):
answer = input('Run again? (y/n): ')
if answer == 'y':
return program()
if answer == 'n':
return False
else:
return None
while restart() == True:
program()
This code is at the bottom
however this didn't seem to work as I answer the question with 'y' or 'n' didn't seem to work as when I answer the program ends. so my question is why doesn't it work and how will you make it work. Thanks.

Computercraft log in system not working with fs API

I'm working on a Windows 8 mock-up OS for Computercraft, and my log in system isn't working. I have been trying to figure it out for the past hour or so and it's really frustrating.
Here's the log in code:
-- Log-in and User Definition Service
--- Variables
userExists = fs.exists("/Users/.config/userConfig.cfg")
termx, termy = term.getSize()
halfx = math.floor(termx*0.5)
halfy = math.floor(termy*0.5)
prompt = "Welcome"
uprompt = "Username: "
pprompt = "Password: "
userConfig = fs.open("/Users/.config/userConfig.cfg", "r")
edituserConfig = fs.open("/Users/.config/userConfig.cfg", "w")
--- Functions
function login(user)
if user == "admin" then
term.setCursorPos(1,1)
term.setTextColor(256)
print (user)
elseif user == "guest" then
print (user)
else
print ("nil")
end
end
function userCheck()
if userExists == true then
term.clear()
term.setBackgroundColor(8)
term.setCursorPos(halfx-0.5*#prompt, halfy - 4)
term.clear()
print (prompt)
term.setCursorPos((halfx-#uprompt), (halfy - 2))
write (uprompt)
term.setCursorPos((halfx-#uprompt), (halfy - 1))
write (pprompt)
term.setCursorPos((halfx), (halfy - 2))
upin = read()
term.setCursorPos((halfx), (halfy - 1))
ppin = read("*")
if upin == userConfig.readLine(21) and ppin == userConfig.readLine(24) then
print ("ADMIN")
elseif upin == userConfig.readLine(33) and ppin == userConfig.readLine(36) then
login("guest")
end
elseif userExists == false then
elseif userExists == nil then
end
end
--- Main
userCheck()
userConfig.cfg:
-- Format as follows:
--
-- (name):
--
-- (prop):
-- "(value)"
--
-- (prop):
-- "(value)"
--
-- (prop):
-- "(value)"
--
--
-- (name):
-- [etc.]
Admin:
user:
"Admin"
pass:
"admin"
auth:
"1"
Guest:
user:
"Admin"
pass:
nil
auth:
"0"
Root:
user:
nil
pass:
nil
auth:
"2"
readLine does not accept arguments and only reads the next line. Your best bet would be to use tables and textutils.serialize to write it all to a file and then when reading use textutils.unserialize to have it inside a table.
Admin:
user:
"Admin"
pass:
"admin"
auth:
"1"
Can be written inside a table such as
{
Admin = {
user = "Admin"
pass = "admin"
auth = "1"
}
Guest = {
user = "Admin"
pass = nil
auth = "0"
}
}
This would work much in the way that you want, and allows for more variability as well as expansion. Of course to read from it is a different story, and i would use a function to find and send either the auth code back, or nil if it didn't work.
Such as
local function findUsers(username,password)
--This will read the file and put all it's data inside a table, and then close it.
local file = fs.open("userConfig.cfg","r")
local userRanks = textutils.unserialize(file.readAll())
file.close()
--To read all the data in a table, i'm going to do this.
for a,v in pairs(userRanks) do
if type(v) == "table" then
if userRanks[a].user == username and userRanks[a].pass == password then
return userRanks[a].auth
end
end
end
--[[If we look through the entire file table, and the username and password aren't the same
as on file, then we say we couldn't find it by returning nil]]--
return nil
end
Now for your input area all you have to do is when they input the username and password just call this afterwards, also if allows you to have the auth code
local auth = findUsers(upin,ppin)
--If they inputted an actual username and password
if auth ~= nil then
--If the auth code from the rank is "1"
if auth == "1" then
--Do whatever stuff you want
elseif auth == "2" then
--Do whatever other stuff for this auth code
end
elseif auth == nil then
print("Oh no you inputted an invalid username and/or password, please try again!"
end
To expand on Dragon53535's answer:
Here's a quick routine I threw together that reads a file into a table:
local function fileToTable(path)
-- first we make sure that the path can be opened
assert(fs.exists(path), path..' does not exist!')
assert(not fs.isDir(path), path..' is a directory!')
local tSrc = {}
local inFile = fs.open(path, 'r')
-- we set line to a non-nil value
local line = ''
-- we continue the loop until line is nil
while line do
-- we read a line from the file
line = inFile.readLine()
-- now we save the value of line to our table
-- line will be nil at EOF
tSrc[#tSrc+1] = line
end
inFile.close()
return tSrc
end
After running userConfig = fileToTable('/Users/.config/userConfig.cfg'), you'd replace something like userConfig.readLine(24) with userConfig[24].
Alternatively, you could check out CC's implementation of the io library. It's a standard Lua library (though in CC it's an fs wrapper), so code can be moved more easily out of CC.
In particular, io.lines() would be helpful here.
The above code rewritten to use io.lines:
local function fileToTable(path)
-- first we make sure that the path can be opened
assert(fs.exists(path), path..' does not exist!')
assert(not fs.isDir(path), path..' is a directory!')
local tSrc = {}
-- iterate over file
-- io.lines is neat, since it opens and closes the file automatically
for line in io.lines(path) do
tSrc[#tSrc+1] = line
end
return tSrc
end
As you can see, this is much smaller (only 9 lines of code!) and more manageable. The reason it's not my preferred solution in CC is that io sits on top of fs, so it's probably better to remove the middleman.
Hope this helps.

Bracket finding algorithm lua?

I'm making a JSON parser and I am looking for an algorithm that can find all of the matching brackets ([]) and braces ({}) and put them into a table with the positions of the pair.
Examples of returned values:
table[x][firstPos][secondPos] = type
table[x] = {firstPos, secondPos, bracketType}
EDIT: Let parse() be the function that returns the bracket pairs. Let table be the value returned by the parse() function. Let codeString be the string containing the brackets that I want to detect. Let firstPos be the position of the first bracket in the Nth pair of brackets. Let secondPos be the position of the second bracket in the Nth pair of brackets. Let bracketType be the type of the bracket pair ("bracket" or "brace").
Example:
If you called:
table = parse(codeString)
table[N][firstPos][secondPos] would be equal to type.
Well, In plain Lua, you could do something like this, also taking into account nested brackets:
function bm(s)
local res ={}
if not s:match('%[') then
return s
end
for k in s:gmatch('%b[]') do
res[#res+1] = bm(k:sub(2,-2))
end
return res
end
Of course you can generalize this easy enough to braces, parentheses, whatever (do keep in mind the necessary escaping of [] in patterns , except behind the %b pattern).
If you're not restricted to plain Lua, you could use LPeg for more flexibility
If you are not looking for the contents of the brackets, but the locations, the recursive approach is harder to implement, since you should keep track of where you are. Easier is just walking through the string and match them while going:
function bm(s,i)
local res={}
res.par=res -- Root
local lev = 0
for loc=1,#s do
if s:sub(loc,loc) == '[' then
lev = lev+1
local t={par=res,start=loc,lev=lev} -- keep track of the parent
res[#res+1] = t -- Add to the parent
res = t -- make this the current working table
print('[',lev,loc)
elseif s:sub(loc,loc) == ']' then
lev = lev-1
if lev<0 then error('too many ]') end -- more closing than opening.
print(']',lev,loc)
res.stop=loc -- save bracket closing position
res = res.par -- revert to the parent.
end
end
return res
end
Now that you have all matched brackets, you can loop through the table, extracting all locations.
I figured out my own algorithm.
function string:findAll(query)
local firstSub = 1
local lastSub = #query
local result = {}
while lastSub <= #self do
if self:sub(firstSub, lastSub) == query then
result[#result + 1] = firstSub
end
firstSub = firstSub + 1
lastSub = lastSub + 1
end
return result
end
function string:findPair(openPos, openChar, closeChar)
local counter = 1
local closePos = openPos
while closePos <= #self do
closePos = closePos + 1
if self:sub(closePos, closePos) == openChar then
counter = counter + 1
elseif self:sub(closePos, closePos) == closeChar then
counter = counter - 1
end
if counter == 0 then
return closePos
end
end
return -1
end
function string:findBrackets(bracketType)
local openBracket = ""
local closeBracket = ""
local openBrackets = {}
local result = {}
if bracketType == "[]" then
openBracket = "["
closeBracket = "]"
elseif bracketType == "{}" then
openBracket = "{"
closeBracket = "}"
elseif bracketType == "()" then
openBracket = "("
closeBracket = ")"
elseif bracketType == "<>" then
openBracket = "<"
closeBracket = ">"
else
error("IllegalArgumentException: Invalid or unrecognized bracket type "..bracketType.."\nFunction: findBrackets()")
end
local openBrackets = self:findAll(openBracket)
if not openBrackets[1] then
return {}
end
for i, j in pairs(openBrackets) do
result[#result + 1] = {j, self:findPair(j, openBracket, closeBracket)}
end
return result
end
Will output:
5 14
6 13
7 12
8 11
9 10

Resources