Menu: Difference between revisions
Logo |
→{{header|J}}: {{lines_too_long}} template |
||
Line 241: | Line 241: | ||
=={{header|J}}== |
=={{header|J}}== |
||
{{lines_too_long}} |
|||
See [[Talk:Select#J_implementation|Talk page]] for explanation of code. |
See [[Talk:Select#J_implementation|Talk page]] for explanation of code. |
||
Revision as of 03:53, 26 January 2010
You are encouraged to solve this task according to the task description, using any language you may know.
Given a list containing a number of strings of which one is to be selected and a prompt string, create a function that:
- Print a textual menu formatted as an index value followed by its corresponding string for each item in the list.
- Prompt the user to enter a number.
- return the string corresponding to the index number.
The function should reject input that is not an integer or is an out of range integer index by recreating the whole menu before asking again for a number. The function should return an empty string if called with an empty list.
For test purposes use the four phrases: 'fee fie', 'huff and puff', 'mirror mirror' and 'tick tock' in a list.
Note: This task is fashioned after the action of the Bash select statement.
AutoHotkey
<lang autohotkey>GoSub, CreateGUI return
Submit: Gui, Submit, NoHide If Input =
GuiControl,,Output
Else If Input not between 1 and 4 {
Gui, Destroy Sleep, 500 GoSub, CreateGUI
} Else {
GuiControlGet, string,,Text%Input% GuiControl,,Output,% SubStr(string,4)
} return
CreateGUI: list = fee fie,huff and puff,mirror mirror,tick tock Loop, Parse, list, `,
Gui, Add, Text, vText%A_Index%, %A_Index%: %A_LoopField%
Gui, Add, Text, ym, Which is from the three pigs? Gui, Add, Edit, vInput gSubmit Gui, Add, Edit, vOutput Gui, Show return
GuiClose: ExitApp</lang>
BASIC
<lang qbasic> function sel$(choices$(), prompt$)
if ubound(choices$) - lbound(choices$) = 0 then sel$ = "" ret$ = "" do for i = lbound(choices$) to ubound(choices$) print i; ": "; choices$(i) next i input ;prompt$, index if index <= ubound(choices$) and index >= lbound(choices$) then ret$ = choices$(index) while ret$ = "" sel$ = ret$
end function</lang>
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
char *menu_select(char **items, char *prompt)
{
int i, nchoices; int choice;
if (items==NULL) return NULL; while(1) { for(i=0; items[i] != NULL; i++) { printf("%d) %s\n", i+1, items[i]); } nchoices = i; if ( prompt != NULL ) printf("%s ", prompt); else printf("Choice? "); scanf("%d", &choice); if ( (choice > 0) && (choice <= nchoices) ) break; printf("Choose from 1 to %d\n\n", nchoices); } return items[choice-1];
}</lang>
<lang c>char *menu[] = {
"fee fie", "huff and puff", "mirror mirror", "tick tock", NULL
};
int main() {
printf("You chose: %s\n", menu_select(menu, "Which is from the three pigs?")); return EXIT_SUCCESS;
}</lang>
C++
<lang C++>#include <iostream>
- include <boost/regex.hpp>
- include <cstdlib>
- include <string>
using namespace std ;
void printMenu( const string * , int ) ; //prints menu bool checkEntry( string , const string * , int ) ; //checks whether entered data is in required range void dataEntry( const string * , int ) ; //function that performs it all
void dataEntry ( const string *terms , int size ) {
if ( size == 0 ) { //we return an empty string when we call the function with an empty list cout << '\n' ; return ; } printMenu ( terms , size ) ; cout << "Enter a number from 1 to " << size << " :\n" ; string entry ; cin >> entry ; bool ok = checkEntry( entry , terms , size ) ; while ( ! ok ) { printMenu( terms , size ) ; cout << "Enter a number from 1 to " << size << " :\n" ; cin >> entry ; ok = checkEntry ( entry , terms , size ) ; } int number = atoi( entry.c_str( ) ) ; cout << *( terms + number - 1 ) << '\n' ;
}
void printMenu ( const string *terms , int num ) {
for ( int i = 1 ; i < num + 1 ; i++ ) { cout << i << ')' << terms[ i - 1 ] << '\n' ; }
}
bool checkEntry( string myEntry , const string *terms , int num ) {
boost::regex e ( "^\\d+$" ) ; if ( ! ( boost::regex_match( myEntry , e ) ) ) return false ; int number = atoi( myEntry.c_str( ) ) ; if ( number < 1 || number > num ) return false ; return true ;
}
int main( ) {
const string terms[ ] = { "fee fie" , "huff and puff" , "mirror mirror" , "tick tock" } ; int size = sizeof terms / sizeof *terms ; dataEntry( terms , size ) ; return 0 ;
} </lang>
Common Lisp
<lang lisp>(defun select (prompt choices)
(if (null choices) "" (do (n) ((and n (<= 0 n (1- (length choices)))) (nth n choices)) (format t "~&~a~%" prompt) (loop for n from 0 for c in choices do (format t " ~d) ~a~%" n c)) (force-output) (setf n (parse-integer (read-line *standard-input* nil) :junk-allowed t)))))</lang>
D
<lang d>import std.stdio; import std.conv; import std.string; void main() {
char[][]items = ["fee fie","huff and puff","mirror mirror","tick tock"]; writefln("You chose %s",doSelect(items));
}
char[]doSelect(char[][]input) {
if (!input.length) return ""; char[]line; int choice; do { writefln("Choose one:"); foreach(i,item;input) { writefln("%d) %s",i,item); } writef("> "); line = readln(); line = chomp(line); choice = ValidChoice(input.length-1,line); } while (choice == -1); // we have a valid choice return input[choice];
}
int ValidChoice(int max,char[]input) {
int tmp; try tmp = toInt(input); catch(Error e) return -1; if (tmp <= max && tmp >= 0) { return tmp; } return -1;
}</lang>
Haskell
<lang Haskell>module RosettaSelect where
import Data.Maybe (listToMaybe) import Control.Monad (guard)
select :: [String] -> IO String select [] = return "" select menu = do
putStr $ showMenu menu putStr "Choose an item: " choice <- getLine maybe (select menu) return $ choose menu choice
showMenu :: [String] -> String showMenu menu = unlines [show n ++ ") " ++ item | (n, item) <- zip [1..] menu]
choose :: [String] -> String -> Maybe String choose menu choice = do
n <- maybeRead choice guard $ n > 0 listToMaybe $ drop (n-1) menu
maybeRead :: Read a => String -> Maybe a maybeRead = fmap fst . listToMaybe . filter (null . snd) . reads</lang>
Example usage, at the GHCI prompt: <lang Haskell>*RosettaSelect> select ["fee fie", "huff and puff", "mirror mirror", "tick tock"] 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Choose an item: 3 "mirror mirror"
- RosettaSelect></lang>
J
See Talk page for explanation of code.
<lang j>require 'misc' select=: ({::~ 'choose a number 0..' _&".@prompt@, ': ',~ ":@<:@# [ i.@# smoutput@,&":&> ' '&,&.>) :: (select@([ smoutput bind 'please choose a valid number'))</lang>
Example use: <lang j> select 'fee fie'; 'huff and puff'; 'mirror mirror'; 'tick tock'</lang>
This would display:
0 fee fie 1 huff and puff 2 mirror mirror 3 tick tock choose a number 0..3:
And, if the user responded with 2, would return: mirror mirror
Java
<lang java5>public static String select(List<String> list, String prompt){
if(list.size() == 0) return ""; Scanner sc = new Scanner(System.in); String ret = null; do{ for(int i=0;i<list.size();i++){ System.out.println(i + ": "+list.get(i)); } System.out.print(prompt); int index = sc.nextInt(); if(index >= 0 && index < list.size()){ ret = list.get(index); } }while(ret == null); return ret;
}</lang>
JavaScript
for the I/O.
<lang javascript>function select(question, choices) {
var prompt = ""; for (var i in choices) prompt += i + ". " + choices[i] + "\n"; prompt += question;
var input; while (1) { WScript.Echo(prompt); input = parseInt( WScript.StdIn.readLine() ); if (0 <= input && input < choices.length) break; WScript.Echo("\nTry again."); } return input;
}
var choices = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock']; var choice = select("Which is from the three pigs?", choices); WScript.Echo("you selected: " + choice + " -> " + choices[choice]);</lang>
Logo
<lang logo>to select :prompt [:options]
foreach :options [(print # ?)] forever [ type :prompt type "| | make "n readword if (and [number? :n] [:n >= 1] [:n <= count :options]) [output item :n :options] print sentence [Must enter a number between 1 and] count :options ]
end
print equal? [huff and puff] (select
[Which is from the three pigs?] [fee fie] [huff and puff] [mirror mirror] [tick tock])
</lang>
OCaml
<lang ocaml>let rec select choices prompt = (* "choices" is an array of strings *)
if Array.length choices = 0 then invalid_arg "no choices"; Array.iteri (Printf.printf "%d: %s\n") choices; print_string prompt; let index = read_int () in if index >= 0 && index < Array.length choices then choices.(index) else select choices prompt</lang>
Perl
<lang perl>sub menu {
my ($prompt,@array) = @_; return unless @array;
print " $_: $array[$_]\n" for(0..$#array); print $prompt; $n = <>; return $array[$n] if $n =~ /^\d+$/ and defined $array[$n]; return &menu($prompt,@array);
}
@a = ('fee fie', 'huff and puff', 'mirror mirror', 'tick tock'); $prompt = 'Which is from the three pigs: ';
$a = &menu($prompt,@a);
print "You chose: $a\n";</lang>
Python
<lang python>def _menu(items):
for indexitem in enumerate(items): print (" %2i) %s" % indexitem)
def _ok(reply, itemcount):
try: n = int(reply) return 0 <= n < itemcount except: return False
def selector(items, prompt):
'Prompt to select an item from the items' if not items: return reply = -1 itemcount = len(items) while not _ok(reply, itemcount): _menu(items) # Use input instead of raw_input for Python 3.x reply = raw_input(prompt).strip() return items[int(reply)]
if __name__ == '__main__':
items = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock'] item = selector(items, 'Which is from the three pigs: ') print ("You chose: " + item)</lang>
Sample runs:
0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: -1 0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: 0 You chose: fee fie >>> ================================ RESTART ================================ >>> 0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: 4 0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: 3 You chose: tick tock
R
Uses menu. <lang R>showmenu <- function() {
choices <- c("fee fie", "huff and puff", "mirror mirror", "tick tock") ans <- menu(choices) if(ans==0) "" else choices[ans]
} str <- showmenu()</lang>
REBOL
<lang REBOL>REBOL [ Title: "Text Menu" Author: oofoe Date: 2009-12-08 URL: http://rosettacode.org/wiki/Select ]
choices: ["fee fie" "huff and puff" "mirror mirror" "tick tock"] choice: ""
valid?: func [ choices [block! list! series!] choice ][ if error? try [choice: to-integer choice] [return false] all [0 < choice choice <= length? choices] ]
while [not valid? choices choice][ repeat i length? choices [print [" " i ":" choices/:i]] choice: ask "Which is from the three pigs? " ] print ["You chose:" pick choices to-integer choice]</lang>
Output:
1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock Which is from the three pigs? klf 1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock Which is from the three pigs? 5 1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock Which is from the three pigs? 2 You chose: huff and puff
Ruby
<lang ruby>def select(prompt, items)
return "" if items.length == 0 while true items.each_index {|i| puts "#{i}. #{items[i]}"} print "#{prompt}: " begin answer = Integer(gets()) rescue ArgumentError redo end return items[answer] if answer.between?(0, items.length - 1) end
end
- test empty list
response = select("Which is empty", []) puts "empty list returns: >#{response}<" puts ""
- "real" test
items = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock'] response = select("Which is from the three pigs", items) puts "you chose: >#{response}<"</lang>
Tcl
<lang tcl>proc select {prompt choices} {
set nc [llength $choices] if {!$nc} {
return ""
} set numWidth [string length $nc] while true {
set i 0 foreach s $choices { puts [format " %-*d: %s" $numWidth [incr i] $s] } puts -nonewline "$prompt: " flush stdout gets stdin num if {[string is int -strict $num] && $num >= 1 && $num <= $nc} { incr num -1 return [lindex $choices $num] }
}
}</lang> Testing it out interactively... <lang tcl>% puts >[select test {}]< >< % puts >[select "Which is from the three pigs" {
"fee fie" "huff and puff" "mirror mirror" "tick tock"
}]<
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: 0
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: skdfjhgz
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs:
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: 5
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: 2 >huff and puff<</lang>
UNIX Shell
The bash shell with its [select] statement. <lang bash>bash$ PS3='Which is from the three pigs: ' bash$ select phrase in 'fee fie' 'huff and puff' 'mirror mirror' 'tick tock'; do > if -n $phrase ; then > PHRASE=$phrase > echo PHRASE is $PHRASE > break > else > echo 'invalid.' > fi > done 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Which is from the three pigs: 5 invalid. Which is from the three pigs: 2 PHRASE is huff and puff bash$</lang>