Main Menu made in QBasic (QB64)? - menu

I've made this menu a long time ago, but I found the file about 2 days ago and I wanted to make it work
CLS
FOR k = 10 TO 65
LOCATE 2, k: PRINT CHR$(222)
LOCATE 23, k: PRINT CHR$(222)
LOCATE 4, k: PRINT CHR$(222)
LOCATE 20, k: PRINT CHR$(222)
NEXT
FOR k = 2 TO 23
LOCATE k, 10: PRINT CHR$(222)
LOCATE k, 65: PRINT CHR$(222)
NEXT
LOCATE 3, 35: PRINT "M A I N M E N U"
LOCATE 6, 15: PRINT "[1] First Option"
LOCATE 8, 15: PRINT "[2] Second Option"
LOCATE 10, 15: PRINT "[3] Third Option"
LOCATE 12, 15: PRINT "[4] Fourth Option"
LOCATE 14, 15: PRINT "[5] Exit"
LOCATE 21, 15: INPUT "Enter your option"; op
Now, I want to make it work, example: if I press 1 it'll automatically go to that option and so on...

Working with integer variables is faster than working with floating point variables. For efficiency reasons you could change your k and op variables into k% and op%.
To blow some live in this menu, you have a number of possibilities. In order of my personal preference:
Using SELECT CASE
DO
CLS
... ' the instructions that build your menu
LOCATE 21, 15: INPUT "Enter your option"; op%
SELECT CASE op%
CASE 1
... ' instructions belonging to 1st option
CASE 2
... ' instructions belonging to 2nd option
CASE 3
... ' instructions belonging to 3rd option
CASE 4
... ' instructions belonging to 4th option
CASE 5
END
END SELECT
LOOP
Using IF
DO
CLS
... ' the instructions that build your menu
LOCATE 21, 15: INPUT "Enter your option"; op%
IF op%=1 THEN
... ' instructions belonging to 1st option
ELSEIF op%=2 THEN
... ' instructions belonging to 2nd option
ELSEIF op%=3 THEN
... ' instructions belonging to 3rd option
ELSEIF op%=4 THEN
... ' instructions belonging to 4th option
ELSEIF op%=5 THEN
END
END IF
LOOP
Using ON GOSUB
DO
CLS
... ' the instructions that build your menu
LOCATE 21, 15: INPUT "Enter your option"; op%
IF op%>0 AND op%<6 THEN
ON op% GOSUB one, two, three, four, five
ENDIF
LOOP
one: ... ' instructions belonging to 1st option
RETURN
two: ... ' instructions belonging to 2nd option
RETURN
three: ... ' instructions belonging to 3rd option
RETURN
four: ... ' instructions belonging to 4th option
RETURN
five: END
The DO ... LOOP makes the program run until the user finally presses 5 to select Exit. Any invalid input will re-display the menu.

Related

Python 3 clear list/restart if total > a set number but it keeps going

Warning: I am new to Python. This code WILL be primitive.
I am appending random numbers into a list until I get to "4".
When adding elements of list...
1. If I get 10, break while loop and print list.
2. If I get <10, resume.
3. If I get > 10, clear list and resume.
So far, the first 2 work. But when it is >4, it just keeps going.
I tried this just using variables and not a list but I had problems with global vs local values.
import random
import time
totalNums = []
count = 1
while count > 0:
rndNum = random.randint(3, 5)
totalNums.append(rndNum)
overLoadCheck = sum(list(totalNums))
print ("Operation #:", count, "Current Num:", rndNum, "Total Nums:", overLoadCheck)
time.sleep(1)
if overLoadCheck > 10:
totalNums.clear
elif overLoadCheck == 10:
break
count = count + 1
print (totalNums)

i want to find the second last element in the list

n=int(input())
arr=[]
i=1
while i<=n:
arr.append(int(input()))
i=i+1
s=len(arr)
sorted(arr)
print(arr[-2])
#error is:
>Traceback (most recent call last):
> File "Solution.py", line 5, in <module>
> arr.append(int(input()))
ValueError: invalid literal for int() with base 10: '2 3 6 6 5'
You're giving input all at once in line number 5 - '2 3 6 6 5'.
Your code expects a single value at a time. Hence for n=5 you need to enter 5 values, one at a time, till your while loop is exhausted.
Solution:
arr=list(map(int, input().split()))
s=len(arr)
sorted(arr)
print(arr[-2])
You were entering a list of elements which were space separated. You don't need n at all. Just split the input and convert each entry to integer and store it in a list.
I have nothing to go off of... but perhaps this will help?!?
n = int(input('give me a number: '))
arr = []
i = 1
while i < n:
print(n)
arr.append(int(input('This does not matter but, I will remember your answer: ')))
i = i + 1
s=len(arr)
sorted(arr)
print('I am going to tell you your second to last "does not matter" answer')
print(arr[-2])
Output:
give me a number: 5
5
This does not matter but, I will remember your answer: 1
5
This does not matter but, I will remember your answer: 2
5
This does not matter but, I will remember your answer: 3
5
This does not matter but, I will remember your answer: 4
I am going to tell you your second to last "does not matter" answer
3
Go with arrayName[-2] or arrayName[len(arrayName) - 2]

How to navigate to indendation levels in vim

I have the following code (line numbers included):
1 def test():
2 a = 1
3 b = 1
4 c = 1
5 d = 1
6 if a == 1:
7 print('This is a sample program.')
And the cursor is on line 7, the last line. Is there a fast, and ideally one key, way to navigate up to line 6, which is one indentation level up, and then, on the next key press, to line 1, one indentation level up again? Conversely, is there a matching method to "drill down" that way?
There is a plugin for that: https://github.com/jeetsukumaran/vim-indentwise
The mappings it provides that match what you are looking for are:
[- : Move to previous line of lesser indent than the current line.
[+ : Move to previous line of greater indent than the current line.
]- : Move to next line of lesser indent than the current line.
]+ : Move to next line of greater indent than the current line.
Then, if you really wanted to do what you asked for in a single keypress, you can remap them like so, for example:
nmap - [-
nmap + ]+

oracle: inter string by parameter and process it

I want to read a string from user then separate words every space character in the string I have this
declare
--counter1 number:=1;
--counter2 number:=1;
--instruction varchar(100);
str varchar2(100):= &inter;
begin
--while true
--loop
--instruction:=substr(str,counter,count2);
--counter2:=counter2+1;
--counter1:=counter1+1;
--exit when instruction = '% ';
--end loop;
SYS.DBMS_OUTPUT.PUT_LINE(str);
end;
but it gives me
Error report -
ORA-06550: line 5, column 21:
PLS-00201: identifier 'TEST_STRING' must be declared
ORA-06550: line 5, column 5:
PL/SQL: Item ignored
ORA-06550: line 14, column 26:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 14, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
and also the exit when instruction = '% '; seems too wrong to me how can I stop on space character
So this error ...
ORA-06550: line 5, column 21:
PLS-00201: identifier 'TEST_STRING' must be declared
... is probably down to this declaration:
str varchar2(100):= &inter;
Even though you are passing a substitution variable you still need to declare the assignment properly, as a string. Like this
str varchar2(100):= '&inter';
Anyway, here is a pure SQL solution.
with cte as
( select 'oracle: inter string by parameter and process it' as str
from dual )
select regexp_substr(str, '[^ ]+', 1, level) as word
from cte
connect by level <= regexp_count(str, chr(32))+1
/
The CONNECT BY is a useful trick to generate a rowset on the fly. Here is the output:
SQL> with cte as ( select 'oracle: inter string by parameter and process it' as str
2 from dual )
3 select regexp_substr(str, '[^ ]+', 1, level) as word
4 from cte
5 connect by level <= regexp_count(str, chr(32))+1
6 /
WORD
------------------------------------
oracle:
inter
string
by
parameter
and
process
it
8 rows selected.
SQL>
You can do this using code similar to:
declare
counter1 number:=1;
counter2 number:=1;
instruction varchar(100);
str varchar2(100):= 'declaration of the type of this expression is incomplete';
begin
while counter1<length(str) loop
while true loop
instruction := substr(str, counter1, counter2);
counter2 := counter2 + 1;
exit when instruction like '% ' or counter1+counter2-1>length(str);
end loop;
dbms_output.put_line(trim(instruction));
counter1 := counter1 + counter2-1;
counter2 := 1;
end loop;
end;
... which gives this output:
declaration
of
the
type
of
this
expression
is
incomplete
It can also be done in several other ways, especially with using function instr() or with regular expressions or with connect by in sql.
You were close, but in your code you did: when instruction = '% ' and should be like '% ' and you unnecessarily increased counter1 in each iteration.

Explanation for the "loop rolling algorithm"

I'm trying to implement the algorithm given by Evgeny Kluev in his answer to loop rolling algorithm
but I'm having trouble getting it to work. Below is an example I tried to work out by hand following his instructions:
text: ababacababd
<STEP 1>
suffixes and LCPs:
ababacababd
4
ababd
3
abacababd
2
abd
1
acababd
0
babacababd
3
babd
2
bacababd
1
bd
0
cababd
0
d
<STEP 2>
sorted LCP array indices: 0,1,5,2,6,3,7,4,8,9
(values) : 4,3,3,2,2,1,1,1,0,0
<STEP 3>
LCP groups sorted by position in text (format => position: entry):
lcp 4:
0: ababacababd
6: ababd
lcp 3:
1: babacababd
2: abacababd
6: ababd
7: babd
lcp 2:
2: abacababd
3: bacababd
7: babd
8: abd
lcp 1:
3: bacababd
4: acababd
8: abd
9: bd
lcp 0:
0: ababacababd
1: babacababd
4: acababd
5: cababd
9: bd
10: d
<STEP 4>
entries remaining after filter (LCP == positional difference):
none! only (abd),(bd) and (bacababd),(acababd) from LCP 1 group
have positional difference equal to 1 but they don't share prefixes
with each other. shouldn't i have at least (ab) and (ba) here?
Can anybody tell me what I'm doing wrong in this process?
Also, he says at the end of step 4 we should have all possible sequences in the text, does he mean all possible repeating sequences?
Is this a known algorithm with a name that I can find more details on elsewhere?
(I'm also confused about his definition of intersecting sequences in step 5, but maybe it would make sense if I understood the preceding steps correctly).
EDIT: Here is what I have for step 4,5,6 after Evgeny's helpful clarification:
<STEP 4>
filter pseudocode:
results = {}
for (positions,lcp) in lcp_groups:
results[lcp] = []
while positions not empty:
pos = positions.pop(0) #pop lowest element
if (pos+lcp) in positions:
common = prefix(input, pos, lcp)
if common.size() < lcp:
next
i = 1
while (pos+lcp*(i+1)) in positions:
if common != prefix(input, pos+lcp*i, lcp):
break
positions.delete(pos+lcp*i)
i += 1
results[lcp].append( (common, pos, i+1) )
application of filter logic:
lcp 4:
0: ababacababd # 4 not in {6}
6: ababd # 10 not in {}
lcp 3:
0: ababacababd # 3 not in {1,2,6,7}
1: babacababd # 4 not in {2,6,7}
2: abacababd # 5 not in {6,7}
6: ababd # 9 not in {7}
7: babd # 10 not in {}
lcp 2:
0: ababacababd # 2 in {1,2,3,6,7,8}, 4 not in {1,2,3,6,7,8} => ("ab", 0, 2)
1: babacababd # 3 in {2,3,6,7,8}, 5 not in {2,3,6,7,8} => ("ba", 1, 2)
2: abacababd # 4 not in {3,6,7,8}
3: bacababd # 5 not in {6,7,8}
6: ababd # 8 in {7,8}, 10 not in {7,8} => ("ab", 6, 2)
7: babd # 9 not in {8}
8: abd # 10 not in {}
lcp 1:
0: ababacababd # 1 in {1,2,3,4,6,7,8,9}, prefix is ""
1: babacababd # 2 in {2,3,4,6,7,8,9}, prefix is ""
2: abacababd # 3 in {3,4,6,7,8,9}, prefix is ""
3: bacababd # 4 in {4,6,7,8,9}, prefix is ""
4: acababd # 5 not in {6,7,8,9}
6: ababd # 7 in {7,8,9}, prefix is ""
7: babd # 8 in {8,9}, prefix is ""
8: abd # 9 in {9}, prefix is ""
9: bd # 10 not in {}
sequences: [("ab", 0, 2), ("ba", 1, 2), ("ab", 6, 2)]
<STEP 5>
add sequences in order of LCP grouping. sequences within an LCP group
are added according to which was generated first:
lcp 4: no sequences
lcp 3: no sequences
lcp 2: add ("ab", 0, 2)
lcp 2: dont add ("ba", 1, 2) because it intersects with ("ab", 0, 2)
lcp 2: add ("ab", 6, 2)
lcp 1: no sequences
collection = [("ab", 0, 2), ("ab", 6, 2)]
(order by position not by which one was added first)
<STEP 6>
recreate input by iterating through the collection in order and
filling in gaps with the normal input:
input = "ab"*2 + input[4..5] + "ab"*2 + input[10..10]
Evgeny, one quick question for you if you happen to look at this again:
Am I doing step 5 correctly? That is, do I add sequences according to which LCP group they were generated from (with higher LCP valued groups coming first)? Or is it something else related to LCP?
Also, if there is anything wrong with step 4 or 6 please let me know, but it seems what I have works very well for this example.
I have to clarify what is meant by "grouping by LCP value" in the original answer. In fact, to the group with selected LCP value we should include all entries with larger LCP values.
This means that for your example, while processing LCP3, we need to merge preceding entries 0 and 6 to this group. And while processing LCP2, we need to merge all preceding entries with LCP3 and LCP4: 0, 1, 2, 6, 7.
As a result two (ab) pairs as well as one (ba) pair are remaining after filter. But since (ba) "intersects" with the first (ab) pair, it is rejected on step 5.
Also, he says at the end of step 4 we should have all possible sequences in the text, does he mean all possible repeating sequences?
That's right, I mean all possible repeating sequences.
Is this a known algorithm with a name that I can find more details on elsewhere?
I don't know. Never seen such algorithm before.
Here is how steps 2 .. 4 may be implemented (in pseudo-code):
for (in_sa, in_src) in suffix_array: # step 2
lcp_groups[max(LCP[in_sa.left], LCP[in_sa.right])].append((in_sa, in_src))
apply(sort_by_position_in_src, lcp_groups) # step 3
for lcp from largest downto 1: # step 4
# sorted by position in src array and unique:
positions = merge_and_uniq(positions, lcp_groups[lcp])
for start in positions:
pos = start
while (next = positions[pos.in_src + lcp]).exists
and LCP.RMQ(pos.in_sa, next.in_sa) >= lcp
and not(prev = positions[pos.in_src - lcp]).exists # to process each
and LCP.RMQ(pos.in_sa, prev.in_sa) >= lcp): # chain only once
pos = next
if pos != start:
pass_to_step5(start, lcp, pos + lcp)
Here I don't plan any particular data structure for positions. But for convenience an ordered associative array is assumed. RMQ is Range Minimum Query, so LCP array should be preprocessed accordingly.
This code is practically the same as the code in OP. But instead of expensive string comparisons (like common != prefix(input, pos+lcp*i, lcp)) it uses RMQ, which (if properly implemented) works almost instantly (and has the same effect as the string comparison because it allows to reject a sub-string when it has too few starting characters in common with preceding sub-string).
It has quadratic worst-case time complexity. Should be slow for input arrays like "aaaaaaaaa". And it's not easy to find its time complexity for "better" strings, probably it is sub-quadratic in "average" case. The same problem could be solved with much simpler quadratic-time algorithm:
def loop_rolling(begin, end):
distance = (end - begin) / 2)
for d from distance downto 1:
start = pos = begin
while pos + d < end:
while (pos + d < end) and (src[pos] == src[pos + d]):
++pos
repeats = floor((pos - start) / d)
if repeats > 0:
pass_to_step5(start, d, start + d * (repeats + 1))
start = pos
Or it may be made even simpler by removing steps 5 and 6. But the variant below has a disadvantage. It is much too greedy, so instead of 5*(ab) it will find 2*(2*(ab))ab:
def loop_rolling(begin, end, distance):
distance = min(distance, (end - begin) / 2))
for d from distance downto 1:
start = pos = begin
while pos + d < end:
while (pos + d < end) and (src[pos] == src[pos + d]):
++pos
repeats = floor((pos - start) / d)
if repeats > 0:
loop_rolling(begin, start, d - 1)
print repeats+1, "*("
loop_rolling(start, start + d, d - 1) # "nested loops"
print ')'
loop_rolling(start + d * (repeats + 1), end, d)
return
else:
if d == 1: print src[start .. pos]
start = pos

Resources