Rapid Euphoria 3.1.1

    The Euphoria Programming Language version 3.1.1 - A programming language that's powerful, easy to learn, free, and a lot more fun than other languages - for Windows, DOS, Linux, FreeBSD and more. Download it, and join a fun community.

You are not logged in.

#1 2019-08-23 11:07:07

shian
Administrator / Администратор

How to write this program in Euphoria 3.1.1?

This is a question, or more an exercise for beginners in programming and in Euphoria.
There are MANY ways to solve this question, and it's fun. Try to find a shorter way to do it...

1. OK, write a program that will print the following on the console (i.e. the "black screen"/the Shell...):

*xxxxxxxxx
x*xxxxxxxx
xx*xxxxxxx
xxx*xxxxxx
xxxx*xxxxx
xxxxx*xxxx
xxxxxx*xxx
xxxxxxx*xx
xxxxxxxx*x
xxxxxxxxx*

2. Now try to write a similar one:

1*********
*2********
**3*******
***4******
****5*****
*****6****
******7***
*******8**
********9*
*********0

3. And what about this one:

0*********
*9********
**8*******
***7******
****6*****
*****5****
******4***
*******3**
********2*
*********1

You can reply to this post with your solutions... Let's see how can we do it in many ways! Each solution can teach us some new aspects of programming in Euphoria.

Offline

#2 2019-08-26 21:38:30

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Weird solution for question 1:

include machine.e    -- using library routine int_to_bits()

for i = 0 to 9 do
    puts(1, (int_to_bits(power(2, i), 10) * ('*' - 'x') + 'x') & '\n')
end for

Pros:
Weird algorithms may be useful in some cases.

Cons:
Slow and hostile code in this case. Hard to understand and hard to maintain!

Offline

#3 2019-08-26 22:03:31

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Lengthy solution for question 1:

position(1, 1)
puts(1, "*xxxxxxxxx")
position(2, 1)
puts(1, "x*xxxxxxxx")
position(3, 1)
puts(1, "xx*xxxxxxx")
position(4, 1)
puts(1, "xxx*xxxxxx")
position(5, 1)
puts(1, "xxxx*xxxxx")
position(6, 1)
puts(1, "xxxxx*xxxx")
position(7, 1)
puts(1, "xxxxxx*xxx")
position(8, 1)
puts(1, "xxxxxxx*xx")
position(9, 1)
puts(1, "xxxxxxxx*x")
position(10, 1)
puts(1, "xxxxxxxxx*")

Pros:
Simple.

Cons:
Long and primitive code. Too much hardwired and not efficient.

Offline

#4 2019-08-27 10:38:23

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Lazy solution for question 1:

-- using library routine putx() from Lib2
include machine2.e   

putx(1, {
    "*xxxxxxxxx",
    "x*xxxxxxxx",
    "xx*xxxxxxx",
    "xxx*xxxxxx",
    "xxxx*xxxxx",
    "xxxxx*xxxx",
    "xxxxxx*xxx",
    "xxxxxxx*xx",
    "xxxxxxxx*x",
    "xxxxxxxxx*"},
'\n')

Pros:
Convenient, simple and clear.

Cons:
Not efficient as it should be. Too much hardwired.

Offline

#5 2019-08-27 11:08:09

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Bloated solution for question 1:

-- shift string s right by one char
function shift_string(integer char, sequence s)
    return char & s[1..$ - 1]   -- $ = length(s)
end function

sequence s

s = '*' & repeat('x', 9)
puts(1, s & '\n')

for i = 2 to 10 do
    s = shift_string('x', s)
    puts(1, s & '\n')
end for

Pros:
Using a function makes the code more modular, and less hardwired.

Cons:
There is of course much more efficient and fast way to achieve this specific goal.

Offline

#6 2019-08-27 13:52:37

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Practical solution for question 1:

sequence s

s = repeat('x', 10)

for i = 1 to 10 do
    s[i] = '*'
    puts(1, s & '\n')
    s[i] = 'x'
end for

Pros:
Efficient, fast and suitable solution.

Cons:
Suitable for this specific task, yet not a modular design.

Offline

#7 2019-08-27 14:56:08

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Practical & Modular solution for question 1:

procedure print_matrix(integer c1, integer c2, sequence s)
    for i = 1 to length(s) do
	s[i] = c1
	puts(1, s & '\n')
	s[i] = c2
    end for
end procedure

print_matrix('*', 'x', repeat('x', 10)) -- modular solution

print_matrix('#', '.', repeat('.', 12)) -- modular example

print_matrix('@', '_', repeat('-', 5))  -- modular example

Pros:
Fast, efficient and modular.

Cons:
Not really.

Offline

#8 2019-08-28 11:52:14

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Practical & Modular & Safe solution for question 1:

type printable_ascii_chr(integer c)
    return c > 31 and c < 127  -- return 0 or 1 (false or true)
end type

type printable_ascii_str(sequence s)
    for i = 1 to length(s) do
	if integer(s[i]) then
	    if s[i] <= 31 or s[i] >= 127 then
		return 0  -- 0 is false
	    end if
	else -- if atom (e.g. 1.45) or a sub-sequence
	    return 0  
	end if
    end for
    return 1  -- 1 is true
end type

procedure print_matrix(printable_ascii_chr c1, 
		       printable_ascii_chr c2, 
		       printable_ascii_str s)
    for i = 1 to length(s) do
	s[i] = c1
	puts(1, s & '\n')
	s[i] = c2
    end for
end procedure

print_matrix('*', 'x', repeat('x', 10))   -- modular solution

print_matrix('#', '.', repeat('.', 12))   -- modular example
print_matrix('@', '_', repeat('-', 5))    -- modular example

print_matrix('*', 128, repeat('.', 10))   -- bug example
print_matrix('*', 'x', "xxxxxxxxx" & 0)   -- bug example

Pros:
Fast, efficient, modular and safe.

Cons:
Not really.

Notes:

  • You achieve safety by using a special function called 'type'.

  • Safety slows down (just a bit) the execution of code, especially when you are using a type for testing a string-sequence (as we are using in this solution). To achieve maximum speed you can disable type-checking at any time by adding

    without type_check

    above your code. (Read the manual for details).

  • Type-checking (safety) will make sure that your code does not include certain logical bugs or run-time bugs which are very hard to trace in some cases.

  • On error (bug) you will also get a detailed description of what leaded to this bug in a special file called "ex.err", in the current directory.

  • You can declare any variable using a 'type' function, for extra safety, especially when your code is using very complex algorithms.

Offline

#9 2019-08-28 15:29:02

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Standard solution for question 1:

include string.e  -- library routine change(), from Lib2

sequence s
s = repeat('x', 10)

for i = 1 to 10 do
    puts(1, change(s, '*', 1, i) & '\n')
end for

Pros:
Using a standard library routine is usually the right choice, it's modular and safer.

Cons:
Library routine is not always optimized for a specific task, hence can be slower then an inline code. (you can compare the speed using the time() function).

Offline

#10 2019-08-29 12:32:13

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Lower level solution for question 1:

include machine.e -- using library routine allocate()

-- it's unlikely to run out of memory, just as safety net...
type memory_address(atom a)
    return a > 0  
end type

-- allocate 100 bytes of memory with 'x's
memory_address m
m = allocate(100)
mem_set(m, 'x', 100)

atom a
a = m

for i = 0 to 9 do
    poke(a + i, '*')
    puts(1, peek({a, 10}) & '\n')
    a += 10
end for

-- free the block of memory
free(m) 

Pros:
Using direct memory access may increase the speed of some operations.

Cons:
Using direct memory access is harder and less safer then using regular variables in this case.
I'm not sure that it's even faster in this case (we need to compare the speed using the time() function).

Offline

#11 2019-08-29 14:06:57

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

C code solution for question 1:

This is the C code that we should compile into a shared library (.so or .dll):

// file name: matrix.c
// print matrix in C programming language,
// let's wrap and run it with Euphoria 3.1.1
//
// compile it as shared library (on Linux) with:
// $ gcc -m32 -shared matrix.c -o matrix.so
//
// see also notes in the page "Manual"->"Instructions for installing Euphoria"

#include <stdio.h>

int main(void) 
{
    int c;
    char array[12] = "xxxxxxxxxx\n";
    
    for (c = 0; c < 10; c++)
    {
	array[c] = '*';
	printf("%s", array);
	array[c] = 'x';
    }
    
    return 0; // 0 is normally exit code "OK"
}

This is the Euphoria code that wraps and executes the C code above:

include dll.e -- using open_dll(), define_c_func()

constant LIB_NAME = "./matrix.so"
atom lib_address
integer id, exit_code

-- open the shared library "matrix.so"
lib_address = open_dll(LIB_NAME)

if lib_address > 0 then
    -- run our program using function "main()" in C code:
    id = define_c_func(lib_address, "main", {}, C_INT)
    exit_code = c_func(id, {})
else
    puts(1, "\nError: cannot find or open '" & LIB_NAME & "' !\n")
    exit_code = 1
end if
	    
abort(exit_code)

Pros:
If you know some C programming - some things can be done better (or only) in C. (this is not relevant to the DOS operating system which is using dos_interrupt() and other functions for similar purposes...).

Cons:
You need to know some C programming, which is somewhat advanced knowledge compare to Euphoria;
Whatever you can do in Euphoria - do in Euphoria! Unlike Euphoria 3.1.1 - C is a hostile language smile.
Using C is less portable and less convenient then using Euphoria only.

Offline

#12 2019-08-30 03:29:09

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Optimized Practical solution for question 1:

This is the original Practical solution:

sequence s

s = repeat('x', 10)

for i = 1 to 10 do
    s[i] = '*'
    puts(1, s & '\n')
    s[i] = 'x'
end for

This is an optimized Practical solution:

sequence s

s = repeat('x', 10) & '\n'  -- we moved   & '\n'   out of the loop 

for i = 1 to 10 do
    s[i] = '*'
    puts(1, s)
    s[i] = 'x'
end for

Pros:
The code is a bit faster.

Cons:
You cannot optimize a code forever. It's all about a schedule and benefit–cost ratio.

Offline

#13 2019-08-30 04:17:22

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Black Box solution for question 1:

atom abc abc=1
for zzz=1 to 2 do
puts(1, repeat('x' , abc-1)&'*')
if abc=1 or abc=6 then 
for ll =1 to 10-abc do puts(1,'x') end for puts(1, '\n')
end if abc=abc+1
if abc=2 or abc=7 then
puts(1, repeat('x' ,abc-1)&'*') for ll= 1 to 10-abc do puts(1,  'x') 
end for puts(1,'\n')
end if
abc=abc+1    if abc=3 or abc=8 then puts(1, repeat( 'x',abc-1)&'*')
for ll = 1 to 10-abc do puts(1, 'x') end for puts(1, '\n')
end if abc=abc+1 
if abc=4 or abc =9 then
puts(1, repeat('x', abc-1)&'*') for ll = 1 to 10-abc do puts(1, 'x') end for 
puts(1, '\n') end if
abc =abc + 1  if abc=5  or abc=10 then 
puts(1, repeat('x',abc-1)&'*') for ll=1 to 10-abc do puts(1,'x') end for 
puts(1,'\n') end if abc=abc+1 end for

Pros:
Not really... miraculously it works......

Cons:
God forbid.
Not readable, Not maintainable, Not modular (I assume...), Not digestible, Terrible, Scary, Hazardous, 18+.

Q&A:
Q: Who can do such thing?
A: An inexperienced programmer under extreme pressure and tight schedule.

Q: Did you ever see such thing in the real life?
A: Yes. In another language called "Ladder Programming".

Q: What to do with such thing?
A: Delete it, delete any backups, make sure the recycle bin is empty.

Offline

#14 2019-09-11 08:02:03

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Optimized-for-speed Practical solution for question 1:

This is the original Practical solution:

sequence s

s = repeat('x', 10)

for i = 1 to 10 do
    s[i] = '*'
    puts(1, s & '\n')
    s[i] = 'x'
end for

This is an optimized-for-speed Practical solution:

sequence s
integer c

s = repeat('x', 110) 
c = 10

for i = 11 to 110 by 11 do
    s[i] = '\n'
    s[i - c] = '*'
    c -= 1
end for

-- output all data at once is much faster, avoiding
-- too much system-call overhead inside the loop
puts(1, s)

Pros:
The code is faster.

Cons:
Again, you cannot optimize a code forever. It's all about a schedule and benefit–cost ratio.
This code is faster but uses more memory.

Offline

#15 2019-09-11 18:51:51

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Recursive solution for question 1:

-- recursive routine
procedure print_matrix(sequence s, integer char, integer pos)
    integer old_chr
    
    if pos <= length(s) then
	old_chr = s[pos]
	s[pos] = char
	puts(1, s & '\n')
	s[pos] = old_chr
	print_matrix(s, char, pos + 1) -- call myself 
    end if
end procedure

print_matrix(repeat('x', 10), '*', 1)   

print_matrix("abcdefg", '.', 1) -- modular example

Pros:
Recursive routine can be very useful, especially in Euphoria, because Euphoria supports unlimited nested sequences (where you can't tell the exact structure or size of a sequence).
Note that unlike in other languages, a recursive routine in Euphoria is not limited by stack size, i.e. a routine can call itself as many times as it needs without running out of stack space.

Cons:
Recursive routine is slower then a simple loop, because each call to itself adds a bit of overhead. (In this specific case it's completely not necessary - a simple loop is much better).
Note that if you are new to programming you might find yourself wondering "which came first: the chicken or the egg?" whenever you see a recursive routine. It may take time to realize what a recursive routine is all about... mad

Offline

#16 2019-09-13 00:36:02

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Fancy solution for question 1:

This is a fancy way to print the matrix on the screen.
(copy/paste to see how it works).

procedure slow_down()
    atom t
    
    t = time()
    while t = time() do
    end while
end procedure

-- return a string of shuffled serial numbers 
-- from 1 to max_num; e.g. {30, 4, 15, 9, ...}
function shuffle_serial_numbers(integer max_num)
    sequence s
    integer random

    s = repeat(0, max_num)
    
    for i = 1 to max_num do
	random = 0
	while find(random, s) do
	    random = rand(max_num)
	end while
	s[i] = random
    end for

    return s
end function

function row_col_char(integer serial_number, integer max_cols)
    integer row, col, char
    
    col = remainder(serial_number, max_cols)
    row = floor(serial_number / max_cols) + (col != 0)
    
    if col = 0 then 
	col = max_cols
    end if
    
    if col = row then
	char = '*'
    else
	char = 'x'
    end if
    
    return {row, col, char}
end function

procedure print_matrix(integer max_rows, integer max_cols)
    sequence s, c
    
    s = shuffle_serial_numbers(max_rows * max_cols) 

    for i = 1 to length(s) do
	c = row_col_char(s[i], max_cols)
	
	position(c[1], c[2])
	puts(1, c[3])
	
	slow_down()
    end for
    
    position(max_rows + 1, 1)
end procedure

print_matrix(20, 20) -- 20 rows x 20 columns matrix

Offline

#17 2019-09-13 14:55:48

shian
Administrator / Администратор

Re: How to write this program in Euphoria 3.1.1?

Standard Fancy solution for question 1:

In the previous Fancy solution for question 1 we are using our own routines, such as
slow_down() and shuffle_serial_numbers(). Well, Lib2 (which extending the standard library of Euphoria 3.1.1) offers more generic and optimized standard routines, which can do a better and safer work then our routines.

In this Standard Fancy solution we will use routines from Euphoria's + Lib2 standard library. By doing this we are essentially making our code more modular and portable.
We will also add colors in this Fancy version, using the graphics.e library.

(copy/paste to see how it works).

-- let's use the standard routines from the standard library:
-- Euphoria 3.1.1
include graphics.e   -- colors
-- Lib2 v1.27+
include machine2.e   -- delay() 
include math.e       -- shuffle(), serial_numbers()

function row_col_char(integer sn, integer max_cols)
    integer row, col, char
    
    col = remainder(sn, max_cols)
    row = floor(sn / max_cols) + (col != 0)
    
    if col = 0 then 
	col = max_cols
    end if
    
    if col = row then
	char = '*'
    else
	char = 'x'
    end if
    
    return {row, col, char}
end function

procedure print_matrix(integer max_rows, integer max_cols)
    sequence s, c
    integer color
    
    bk_color(BLACK)
    clear_screen()
    
    s = shuffle(serial_numbers(1, max_rows * max_cols, 1)) 

    for i = 1 to length(s) do
	c = row_col_char(s[i], max_cols)
	
	if c[3] = '*' then
	    color = YELLOW
	elsif rand(2) = 2 then
	    color = BRIGHT_CYAN
	else
	    color = BRIGHT_MAGENTA
	end if
	text_color(color)
	
	position(c[1], c[2])
	puts(1, c[3])
	
	delay(rand(10))
    end for
    
    position(max_rows + 1, 1)
end procedure

print_matrix(20, 20) -- 20 rows x 20 columns matrix

Offline

Board footer

Powered by FluxBB