I was asked this question and could not come up with a solution, hope to find it here.
We need a function that receives a number (X) and a string, it needs to print that string X number of times, without using any loops or if-else conditions.
It's more about a generic algorithm not a specific programming language.
My initial response was recursion, but it requires an IF clause.
func (int x, string namme)
{
if(x>0)
{
print (name);
func(x-1);
}
}
In general case, you cannot do that. Even recursion's terminal case requires condition. The only solution in such case is ... Template magic (surprise!)
Here is the solution:
template <int times>
void print(const string& str);
template <>
void print<0>(const string& str)
{
}
template <int times>
void print(const string& str)
{
cout << str << " ";
print<times - 1>(str);
}
Such approach requres from you compile time value of number of times. But result code will not contain any conditions (you can see asm code)
Example of usage:
print<5>("Yeah!");
You can use a little trick in c++:
ยง4.7/4 (Integral Conversion)
If the source type is bool, the value false is converted to zero and the value true is converted to one.
This means you can index an array using a boolean value. If your array contains function pointers you implemented an if/else statement.
void noop(int,std::string) {}
void print_n_times(int times, std::string text) {
void (*next_function[])(int,std::string) = {
noop,
print_n_times
};
next_function[(times-1)>0](times-1, text);
std::cout << times << ' ' << text << '\n';
}
See it live
You can do the same thing in python:
Python 2.7.12 (default, Oct 10 2016, 12:56:26)
[GCC 5.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def noop(times,text):
... pass
...
>>> def print_n_times(times,text):
... next_function = [noop, print_n_times]
... print(text);
... next_function[int((times-1)>0)](times-1, text)
...
>>> print_n_times(4, "Hello World!")
Hello World!
Hello World!
Hello World!
Hello World!
Here is a complete program demonstrating this. I would not recommend writing anything like this in Real Life.
This takes advantage of the fact that subtracting 1 from 0 will set the most significant bit in an integer. I shift bit 63 down to 0 to get either a 1 or 0 (i.e. to avoid a conditional) and call one of two functions. runtime.Goexit will terminate a goroutine, but will call all deferred functions in the process. This unlocks a mutex that lets the sillyString function terminate only after all of the prints have happened.
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
sillyString("omg", 10)
}
func sillyString(s string, n int) {
var m sync.Mutex
m.Lock()
go func() {
defer m.Unlock()
mustGoDeeper(s, uint64(n-1), []func(){runtime.Goexit, func() {}})
}()
m.Lock()
}
func mustGoDeeper(s string, n uint64, fs []func()) {
sig := (1 - int(n>>63))
fs[sig]()
fmt.Printf("%s\n", s)
mustGoDeeper(s, n-1, fs)
}
Recursion looks like a good way to go, but we need to stop an infinite recursion. That means being sneaky. Using a try ... catch can do the job, at least in a language which supports that construct:
void printXtimes(String text, int x) {
try {
int z = 100 / x;
} catch (Exception ex) {
// Zero divide so exit program.
exit(0);
}
println(text);
printXtimes(text, x-1);
} // end printXtimes()
That is a Java-like pseudocode. In real Java the compiler gives a warning about infinite recursion, but it compiles and runs correctly, printing the text message the given number of times. An interesting problem.
Related
A cordial greeting.
I'm learning yacc in golang and i created this file:
%{
package main
import (
"fmt"
)
%}
%union{
ex string
}
%token <ex> DB OTHER_DB
%%
query: other
|
db
;
db: DB
{
fmt.Printf("\tDB: %s\n", $1 )
}
;
other: OTHER_DB
{
fmt.Printf("\tOTHER_DB: %s\n", $1 )
}
;
%%
type mlex struct {
expr string
result int
}
func (f *mlex) Lex(lval *yySymType) int {
yyErrorVerbose = true
return 0
}
func (f *mlex) Error(s string) {
fmt.Printf("syntax error: %s\n", s)
}
func Parse(expr string) int {
m := &mlex{expr, 0}
yyParse(m)
return m.result
}
but when executing it I get this error:
syntax error: syntax error: unexpected $end, expecting DB or OTHER_DB
I have been testing this yacc file with this code:
package main
import (
"fmt"
)
func main() {
res := Parse("db")
fmt.Println(res)
}
What could it be ? Will I need anything else in the yacc file?
I am trying to make a very simple, fully functional example to understand it well.
Thanks for your time.
When your parser needs to know what the next input symbol ("token") is, it calls the yyLexer's Lex method. Your implementation of that makes no attempt to read a token. Instead, it just returns 0:
func (f *mlex) Lex(lval *yySymType) int {
yyErrorVerbose = true
return 0
}
So from the parser's perspective, it is being given an empty input stream, regardless of what input you might actually have provided. It then attempts to parse this empty input, but your grammar doesn't permit it. The only valid inputs start with the tokens DB or OTHER_DB, and it doesn't see either of those things.
So it produces the error message, detailing exactly what its problem is. (The parser represents the end of input with the internal pseudo-token $end, in case that was confusing you.)
I created a very small game of number guessing in Go. The thing is, it executes differently under Windows and under Linux. By executing it on Ubuntu for example, everything works just fine. But when I try to start it under Windows, it compiles just fine but during execution when I enter something (for example 5) it prints me twice "Smaller than random num"or "Bigger than random num". I have no idea why it happens.
package main
import (
"fmt"
"math/rand"
"time"
)
func main () {
var number int //declaration
var tries int = 0
random_number := random(1, 9) //gets random number
for ; ;tries++ {
//fmt.Printf("Enter your prediction: ")
fmt.Scanf("%v",&number)
if number == random_number {
break;
} else if number<random_number{
fmt.Printf("Smaller than random num\n")
} else {
fmt.Printf("Bigger than random num\n")
}
}
fmt.Printf("You guessed correctly in %v tries",tries)
}
func random(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max - min) + min
}
Newlines are different in Linux and Windows, and thus your program behaves differently.
See this issue: https://github.com/golang/go/issues/5391
To fix this, you can replace your Scanf with this (note the "\n" at the end):
fmt.Scanf("%v\n",&number)
The following code generates a syntax error (unexpected ++ at end of statement) in Go 1.6 or 1.7:
package main
import "fmt"
var x int
func increment() int {
return x++ // not allowed
}
func main() {
fmt.Println( increment() )
}
Shouldn't this be permitted?
It's an error, because the ++ and -- in Go are statements, not expressions: Spec: IncDec Statements (and statements have no results that would be returned).
For reasoning, see Go FAQ: Why are ++ and -- statements and not expressions? And why postfix, not prefix?
Without pointer arithmetic, the convenience value of pre- and postfix increment operators drops. By removing them from the expression hierarchy altogether, expression syntax is simplified and the messy issues around order of evaluation of ++ and -- (consider f(i++) and p[i] = q[++i]) are eliminated as well. The simplification is significant. As for postfix vs. prefix, either would work fine but the postfix version is more traditional; insistence on prefix arose with the STL, a library for a language whose name contains, ironically, a postfix increment.
So the code you wrote can only be written as:
func increment() int {
x++
return x
}
And you have to call it without passing anything:
fmt.Println(increment())
Note that we would be tempted to still try to write it in one line using an assignment, e.g.:
func increment() int {
return x += 1 // Compile-time error!
}
But this also doesn't work in Go, because the assignment is also a statement, and thus you get a compile-time error:
syntax error: unexpected += at end of statement
The accepted solution is right that the OP's code does not work because in go increment/decrement(x++/x--) statements are expressions that don't return a value.
However the solution presented has a slightly different effect than the original request.
x++ would return the value of x then increment in C like syntax.
however the opposite would happen if you do it this way:
x++
return x
You can negate that issue by reducing your initial value by one or by using a defer statement as written here:
func incr() int {
defer func() { counter++ }()
return counter
}
https://play.golang.org/p/rOuAv7KFJQw
in go tutorial following code is often seen:
a := foo()
b, c := foo()
or actually what I see is:
m["Answer"] = 48
a := m["Answer"]
v, ok := m["Answer"]
how many foo() is defined?
Is it two, one with one return type, another with two return type?
Or just one foo() with two return type defined, and somehow magically when only need one return value (a := foo()), another return value is omitted?
I tried
package main
func main() {
a := foo()
a = 1
}
func foo() (x, y int) {
x = 1
y = 2
return
}
func foo() (y int) {
y = 2
return
}
But I got error message foo redeclared in this block
While some built in operations support both single and multiple return value modes (like reading from a map, type assertions, or using the range keyword in loops), this feature is not available to user defined functions.
If you want two versions of a function with different return values, you will need to give them different names.
The Effective Go tutorial has some good information on this.
Basically, a function defines how many values it returns with it's return statement, and it's function signature.
To ignore one or more of the returned values you should use the Blank Identifier, _(Underscore).
For example:
package main
import "fmt"
func singleReturn() string {
return "String returned"
}
func multiReturn() (string, int) {
return "String and integer returned", 1
}
func main() {
s := singleReturn()
fmt.Println(s)
s, i := multiReturn()
fmt.Println(s, i)
}
Playground
The v, ok := m["answer"] example you've given is an example of the "comma, ok" idiom (Also described in the Effective Go link above). The linked documentation uses type assertions as an example of it's use:
To extract the string we know is in the value, we could write:
str := value.(string)
But if it turns out that the value does not contain a string, the program will crash with a run-time error. To guard against that, use the "comma, ok" idiom to test, safely, whether the value is a string:
str, ok := value.(string)
if ok {
fmt.Printf("string value is: %q\n", str)
} else {
fmt.Printf("value is not a string\n")
}
If the type assertion fails, str will still exist and be of type string, but it will have the zero value, an empty string.
Consider the following (useless) Go function:
func domagic(n int) int {
if n > 10 {
return n;
} else {
return 0;
}
}
This gives me the following compiler error:
main.go:15: function ends without a return statement
However, if i return a value outside the if-else block (before the end of the function), it compiles without errors.
Is this behavior by design, or is it something simply not yet implemented in the Go MinGW compiler?
Simple googling for the exact compiler error message yields this bugtracker issue. So I'd not say it's "by design" as it looks more like "it'd just happened to be implemented this way". See also this thread.
It's by design. Write:
package main
import "fmt"
func domagic(n int) int {
if n > 10 {
return n
}
return 0
}
func main() {
fmt.Println(domagic(7), domagic(42))
}
Output:
0 42