LUA: Reading text after reading number does not work - text

I am struck with the io.read command in LUA. The example below jumps over the text-read line. That only happens if there is a number input before.
repeat
print("Input number!")
number=io.read("*n")
print("Would you like do to this again? (y/n)")
again = io.read()
until again == "n"
I tried this in two IDEs (repl and ZeroBrane) and it drives me MAAAD!!!
Cany anyone help, please?
Cheers,
Ulrich

Try reading line by line as string and convert string to number using tonumber()
repeat
print("Input number!")
num = tonumber(io.read())
print('Would you like do to this again? (y/n)')
again = io.read()
until again == 'n'
While debugging, I see that second io.read is using the buffer started just after your number ends.
Your code with some more prints
repeat
print("Input number!")
-- num = tonumber(io.read())
num = io.read('*n')
print('you entered-> ' .. tostring(num))
print('Would you like do to this again? (y/n)')
again = io.read()
print('your choise from (y/n)-> ' .. again)
until again == 'n'
output
Input number!
234
you entered-> 234
Would you like do to this again? (y/n)
your choise from (y/n)->
Input number!
234y
you entered-> 234
Would you like do to this again? (y/n)
your choise from (y/n)-> y
Input number!
234234n
you entered-> 234234
Would you like do to this again? (y/n)
your choise from (y/n)-> n
This description is from Programming in Lua: 21.1
The call io.read("*number") reads a number from the current input file. This is the only case where read returns a number, instead of a string. When you need to read many numbers from a file, the absence of the intermediate strings can make a significant performance improvement. The *number option skips any spaces before the number and accepts number formats like -3, +5.2, 1000, and -3.4e-23. If it cannot find a number at the current file position (because of bad format or end of file), it returns nil.
Please apologize for the poor description.

Related

Sort function in Python is bugged?

I know this doubt looks quite easy but i just cant get my head to wrap around it.
I was just fooling around with python sorting, when i noticed this.
If I gave in the input as 21 ,8, 4. The output i would receive would be 21, 4,8. Not 4,8,21. What i am assuming is that python is only taking the first digit and comparing, but that is not what i want. How do i fix this problem?
lst=list()
i=0
while i < 3:
number=input("Give me a number: \n")
lst.append(number)
i=i+1
print("\n")
lst.sort()
print("The list of ordered numbers are:")
for j in lst:
print(j)
Terminal output
The only mistake you are making is by taking input as string,
The line number=input("Give me a number: \n") should be number=int(input("Give me a number: \n"))
If you use input() only then it takes every input as string, you need to convert that to int in your case, using int()
The sort function works on both integers and strings.
But if you want it to be implemented for the integers, you need to accept the input as integers for which you can use something like this.
lst=list()
i=0
while i < 3:
number=int(input("Give me a number: \n"))
lst.append(number)
i=i+1
print("\n")
lst.sort()
print("The list of ordered numbers are:")
for j in lst:
print(j)

Validate the user's input of only 0's and 1's

I have to convert an 8-bit binary number to a decimal number. I believe that I have the conversion correct along with validating if the user inputted an 8-bit binary number (no more, no less) but I am stuck on validating the user's input for only 0's and 1's.
Any help would be great. I feel like I am overthinking this but I tried everything.
Here is the code I have:
while True:
binary = input("Please enter a 8-bit binary number: ")
if len(binary) < 8 or len(binary) > 8:
print("Must be an 8 bit binary!")
else:
print(int(binary, 2))
break
Ok, first thing first, you use this line:
if len(binary) < 8 or len(binary) > 8:
it is way more readable to just say:
if len(binary) != 8
Now this is how I would implement your code:
while True:
binary = input("Please enter a 8-bit binary number: ")
for item in binary:
if item not in {'0','1'}:
print("Must only contains 0's and 1's !")
break
if len(binary) != 8:
print("Must be an 8 bit binary!")
else:
print(int(binary, 2))
break
Note that this will check for both validations you expected while providing a relevant insight to the user depending on his particular mistake.
You're checking the length, but not validating the users input. eg,
s = '12345678' is a valid input into your code.
If you really want to validate, you could do something simple like
s1 = '11010101111'
if s1.count('1') + s1.count('0') == len(s1):
print(int(s1,2))
If you're a fan of regexes:
import re
s1='10010011'
print(re.match(r'[10]{8}', s1) is None)
This will match 10010011, but not 110010100 or 12345689 or 12345678.

Option to save output printed on screen as a text file (Python)

Either I'm not using the right search string or this is buried deep within the interwebs. I know we aren't supposed to ask for homework answers, but I don't want the code answer, I want to know where to find it, cause my GoogleFu is busted.
Assignment is to create a program that will roll two 6-sided dice n times, with n being user-defined, between 1 and 9. The program then displays the results, with "Snake Eyes!" if the roll is 1-1, and "Boxcar!" if the roll is 6-6. It also has to handle ValueErrors (like if someone puts "three" instead of "3") and return a message if the user chooses a number that isn't an integer 1-9.
Cool, I got all that. But he also wants it to ask the user if they want to save the output to a text file. Um. Yeah, double-checked the book, and my notes, and he hasn't mentioned that AT ALL. So now I'm stuck. Can someone point me in the right direction, or tell me what specifically to search to find help?
Thanks!
Check out the input function:
https://docs.python.org/3.6/library/functions.html#input
It will allow you to request input from a user and store it in a variable.
You can do something like this to store your final output to a text file.
def print_text(your_result):
with open('results.txt', 'w') as file:
file.write(your_result)
# Take users input
user_input = input("Do you want to save results? Yes or No")
if(user_input == "Yes"):
print_text(your_result)
I hope this helps
Well, it's not pretty, but I came up with this:
def print_text():
with open('results.txt', 'w') as file:
file.write(str(dice))
loop = True
import random
min = 1
max = 6
dice = []
while loop is True:
try:
rolls = int(input("How many times would you like to roll the dice? Enter a whole number between 1 and 9: "))
except ValueError:
print("Invalid option, please try again.")
else:
if 1 <= rolls <= 9:
n = 0
while n < rolls:
n = n + 1
print("Rolling the dice ...")
print("The values are:")
dice1 = random.randint(min, max)
dice2 = random.randint(min, max)
dice.append(dice1)
dice.append(dice2)
print(dice1, dice2)
diceTotal = dice1 + dice2
if diceTotal == 2:
print("Snake Eyes!")
elif diceTotal == 12:
print("Boxcar!")
else: print("Invalid option, please try again.")
saveTxt = input("Would you like to save as a text file? Y or N: ")
if saveTxt == "Y" or saveTxt == "y":
print_text()
break

Python 3.5.1 Introduction to Python 2.1 Mark Clarkson - While Loop Issue

I'm working my way through this set of tutorials. In section 3.2a - While Loops the following code is supposed to loop until the user enters the target number (7) then display a congratulations message however regardless of what number is entered Python either gives a right answer or a wrong answer, even 7 will sometimes flag a wrong answer. I know there are other ways to perform this sort of task but I would like to get the code from the tutorial working.
targetNumber = 7
guess = input("Guess a number between 1 and 10 ")
while guess != targetNumber:
print("Wrong, try again ")
guess = input("Guess a number between 1 and 10 ")
print("Congratulations - that's right!")
You should convert the target numger to an string before comparison. Also, you should exclude the congratulations message from the loop. I would suggest :
targetNumber = str(7)
guess = input("Guess a number between 1 and 10 ")
while guess != targetNumber:
print("Wrong, try again ")
guess = input("Guess a number between 1 and 10 ")
print("Congratulations - that's right!")
The detail is that input returns a string and if you compare a string to an integer, it will always return false.
Python's input function (or raw_input in Python 2.x) returns a string entered by the user. targetNumber, on the other hand, is an integer. In the Python Interpreter, try:
>>> 7 == "7"
False
You need to cast the user's input to an integer first.
try:
guess = int(input("Please enter a number: "))
except ValueError:
print("That is not a valid number!")

using .find for multiple letters in a string

I'm working on a hobby project. I'm attempting to make a hangman game in Python. So far everything works nice. There's just one problem. If I type a letter that appears in the word two times, I can't get the second letter to appear. I've been toying around with string.find and string.count methods but to no avail. Does anyone have an idea how I would go about doing this? I'm stumped.
#!bin/bash/python
import os
import time
word = 'megalopolis'
l = len(word)
list = []
n=0
while n!=l:
list.append('-')
n+=1
os.system('cls' if os.name=='nt' else 'clear')
print list
i=3
while i!=0:
x = raw_input('Enter a letter: ')
if x in word and x!='':
print 'Good choice!'
count=word.count(x)
loc=word.find(x)
print count
print loc
list[loc]=x
os.system('cls' if os.name=='nt' else 'clear')
if '-' not in list:
break
print list
else:
print 'Sorry...'
i-=1
if i==2:
print 'You have '+`i`+' more chances.'
if i==1:
print 'You have '+`i`+' more chance!'
time.sleep(1)
os.system('cls' if os.name=='nt' else 'clear')
print list
if '-' not in list:
print 'YOU WIN!!'
else:
print 'GAME OVER!!'
x = raw_input('press enter')
If you just need the index of every character occurence:
indexes = [idx for idx, ch in enumerate(word) if ch == x]
Perhaps you should use Unidecode to keep the accents in words, it might be useful depending on the language (if not English). Also, you can use str.lower() or str.upper() methods to ensure every word and trial is in the same case.
The string module has useful constants for you (e.g. ascii_uppercase).
However, in this game you don't need to worry about any index. I've made another version for you:
#!/usr/bin/env python
from string import ascii_uppercase
word = "megalopolis".upper() # Top-secret!
trial = 3 # Total trials available (number of mistakes to lose the game)
typed = set() # Typed characters
word_letters = set(word)
while trial:
print
print "".join(ch if ch in typed else "-" for ch in word)
# Winning condition
if typed.issuperset(word_letters):
break
# Data input
x = raw_input("Enter a letter: ").upper()
# Error cases
if len(x) != 1:
print "Invalid input."
continue
if x in typed:
print "Already typed."
continue
if x not in ascii_uppercase:
print "What you typed isn't a letter."
continue
# Valid data cases
typed.add(x)
if x in word:
print "Good choice!"
else:
print "{} not found!".format(x),
trial -= 1
if trial == 1:
print "You have one more chance!"
elif trial > 1:
print "You have {} more chances.".format(trial)
else:
print 'Sorry...'
# Ending message
print
if trial:
print "YOU WIN!!"
else:
print "GAME OVER!!"
Hashbang: Your shebang should usually start with "#!/". You're probably using Windows, so the "bin" as a relative directory wasn't used by you.
"l" / l as a variable name should be avoided! It might be seen as one or lower "L" (PEP8), or even a pipe "|". PS: At the beginning of this item, I typed the same letter here twice.
There's no need to use "list" as a variable name here, and you shouldn't do, as that's a built-in name.
Multiplication like "txt" * 3 returns "txttxttxt" (it repeats the data) for both strings and lists
Neither "cls" nor "clear" worked here, showing
"TERM environment variable not set."
instead of clearing the console screen. I replaced these with an empty
"print", and removed the time sleep. Look for subprocess if you want to call something from console (although I'd also look for curses if there's a need to do some CLI visualization).
Suppose x is a string. When x == "", bool(x) is False, else bool(x) is True.
Suppose x is an integer. When x == 0, bool(x) is False, else bool(x) is True.
Avoid backticks (`). No one uses them today in Python, they doesn't exist in Python 3 and you can use the repr built-in instead. However, you probably wanted something like str(trial), "%d" % trial or "{}".format(trial).
The last "press enter" probably has to do with an operating system "auto-close-after-finish" behaviour, but you [at least] didn't need to store it in x.
I've used a generator expression. You should read here about list comprehensions if the "for" in the middle of one line is confusing for you. Python developers use generator expressions and list comprehensions all the time, you shouldn't avoid learning about them.
I replaced the original winning evaluation to a comparison between the set of characters the word originally has and the set of typed characters (both uppercase).
If there's something here you didn't understand, please ask a new question.
This SO question ought to cover it for you:
Finding multiple occurrences of a string within a string in Python
It should work just as well for individual characters as strings, considering how easy it is to form the second from the first.
So in the end, I wound up doing it this way:
if x in word and x!='':
count=word.count(x)
loc=0
while count==1 or count>1:
loc=word.find(x,loc)
list[loc]=x
loc+=1
count-=1
print 'Good choice!'
Thanks for your help everyone. I definitely learned something.

Resources