Skip to content

Commit

Permalink
Merge pull request #900 from RFigCon/main
Browse files Browse the repository at this point in the history
Implementation of Train in Lua and D
  • Loading branch information
coding-horror authored Jun 2, 2024
2 parents 998110f + a4cff3b commit e8fb61f
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 0 deletions.
3 changes: 3 additions & 0 deletions 00_Alternate_Languages/91_Train/D/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Original source downloaded from [Vintage Basic](http://www.vintage-basic.net/games.html).

Conversion to [MiniScript](https://dlang.org).
50 changes: 50 additions & 0 deletions 00_Alternate_Languages/91_Train/D/train.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import std.stdio;
import std.random : uniform;

float abs(float num) {
if(num<0){
return num*-1;
}

return num;
}

void main() {

writeln("\nTIME - SPEED DISTANCE EXERCISE");

bool keep_playing = true;
float error_margin = 5.0;

while(keep_playing){
int car_speed = uniform!"[]"(40,65); //Random number between 40 and 65
int delta_time = uniform!"(]"(4,20); //Between 5 and 20
int train_speed = uniform!"[)"(20,40); //Between 20 and 39; This is the default if not specified: uniform(x,y)

writeln("\nA CAR TRAVELING AT ", car_speed, " MPH CAN MAKE A CERTAIN TRIP IN ", delta_time,
" HOURS LESS THAN A TRAIN TRAVELING AT ", train_speed, "MPH." );

float input;
write("HOW LONG DOES THE TRIP TAKE BY CAR? ");
readf!"%f\n"(input);

float car_time = cast(float)delta_time * train_speed / (car_speed - train_speed);
int percent = cast(int)( abs(car_time-input) * 100 / car_time + .5);

if(percent > error_margin){
writeln("SORRY. YOU WERE OFF BY ", percent, " PERCENT.");
}else{
writeln("GOOD! ANSWER WITHIN ", percent, " PERCENT.");
}
writeln("CORRECT ANSWER IS ", car_time, " HOURS.");

string answer;
write("\nANOTHER PROBLEM (YES OR NO)? ");
readf!"%s\n"(answer);

if( !(answer == "YES" || answer == "Y" || answer == "yes" || answer == "y") ){
keep_playing = false;
}
}

}
268 changes: 268 additions & 0 deletions 90_Tower/lua/tower.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
print [[
TOWERS
CREATIVE COMPUTING MORRISTOWN, NEW JERSY
]]

local MAX_DISKS <const> = 7
local MAX_DISK_SIZE <const> = 15
local MAX_MOVES <const> = 128
local NUM_TOWERS <const> = 3

local towers = {
{ size = 0, elem = {} },
{ size = 0, elem = {} },
{ size = 0, elem = {} },
}

local total_disks
function ask_how_many_disks()

local keep_asking = true
local input
local errors = 0

while keep_asking do

io.write(string.format("HOW MANY DISKS DO YOU WANT TO MOVE (%d IS MAX)? ", MAX_DISKS) )
input = io.read("*number")
io.read() --get rid of the remaining newline character

if input ~= nil and input>0 and input<=MAX_DISKS then
keep_asking = false

else
errors = errors + 1
if errors > 2 then
print "ALL RIGHT, WISE GUY, IF YOU CAN'T PLAY THE GAME RIGHT, I'LL"
print "JUST TAKE MY PUZZLE AND GO HOME. SO LONG."
os.exit()
end

print "SORRY, BUT I CAN'T DO THAT JOB FOR YOU."
end
end
total_disks = input
end

function init_game()
print("TOWERS OF HANOIR PUZZLE\n") --'\n' indicates a new line

print "YOU MUST TRANSFER THE DISKS FROM THE LEFT TO THE RIGHT TOWER,"
print "ONE AT A TIME, NEVER PUTTING A LARGER DISK ON A SMALLER DISK.\n"

ask_how_many_disks()

print() -- print() already creates a new line at the end, so an empty print leaves an empty line
print "IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE."
print "3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE, 7 THE"
print "NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH 2 DISKS,"
print "THEIR CODE NAMES WOULD BE 13 AND 15, ETC. THE NEEDLES ARE"
print "NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL START WITH THE"
print "DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM TO NEEDLE 3.\n"

print "GOOD LUCK!\n"

local i = 1
local max = MAX_DISK_SIZE
while i<= total_disks do
towers[1].elem[i] = max
max = max-2
i = i+1
end

towers[1].size = total_disks

local idx = 2
while idx <= NUM_TOWERS do
towers[idx].size = 0
end
end

function print_towers()
local line = MAX_DISKS

while line > 0 do
local twr = 1

while twr <=3 do
local rpt = 10
local offset = 0
if line <= towers[twr].size then
offset = (towers[twr].elem[line] - 1) / 2
rpt = rpt - offset
end
io.write( string.rep(' ', rpt) )
io.write( string.rep('*', offset) )
io.write '*'
io.write( string.rep('*', offset) )
io.write( string.rep(' ', rpt) )
twr = twr + 1
end
print ''
line = line - 1
end

end

function ask_which_disk()

local keep_asking = true
local input
local errors = 0
while keep_asking do

io.write("WHICH DISK WOULD YOU LIKE TO MOVE? ")
input = io.read("*number")
io.read() --get rid of the remaining newline character

if input==nil or input > MAX_DISK_SIZE or input%2==0 or input <= MAX_DISK_SIZE-(total_disks*2) then
print "ILLEGAL ENTRY... YOU MAY ONLY TYPE 3,5,7,9,11,13 or 15."
errors = errors + 1
if errors > 1 then
print "STOP WASTING MY TIME. GO BOTHER SOMEONE ELSE."
os.exit()
end

--[[
Since there are only 3 towers, it's easier to do an 'if' with three
conditions than to do a loop
]]
elseif towers[1].elem[ towers[1].size ] ~= input and
towers[2].elem[ towers[2].size ] ~= input and
towers[3].elem[ towers[3].size ] ~= input then

print "THAT DISK IS BELOW ANOTHER ONE. MAKE ANOTHER CHOICE."
else
keep_asking = false
end
end

return input
end

function ask_which_needle(dsk)

local keep_asking = true
local input
local errors = 0

while keep_asking do

io.write("PLACE DISK ON WHICH NEEDLE? ")
input = io.read("*number")
io.read() --get rid of the remaining newline character

if input~=nil and towers[input].size > 0 and towers[input].elem[ towers[input].size ] < dsk then
print "YOU CAN'T PLACE A LARGER DISK ON TOP OF A SMALLER ONE,"
print "IT MIGHT CRUSH IT!"
return 0

elseif input~=nil and input>=1 and input<=3 then
keep_asking = false

else
errors = errors + 1
if errors > 1 then
print "I TRIED TO WARN YOU, BUT YOU WOULDN'T LISTEN."
print "BYE BYE, BIG SHOT."
os.exit() --Stop program
else
print "I'LL ASSUME YOU HIT THE WRONG KEY THIS TIME. BUT WATCH IT,"
print "I ONLY ALLOW ONE MISTAKE."
end
end
end
return input
end

function is_game_over()
if towers[1].size == 0 and towers[2].size == 0 then
return true
else
return false
end
end

function game_loop()
local moves = 0
local dsk
local twr_to
local twr_fr

while not is_game_over() do
moves = moves + 1

if moves > MAX_MOVES then
print(string.format("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN %d MOVES.", MAX_MOVES))
os.exit()
end


repeat
dsk = ask_which_disk()
twr_to = ask_which_needle(dsk)
until twr_to ~= 0


if towers[1].elem[ towers[1].size ] == dsk then
twr_fr = 1
elseif towers[2].elem[ towers[2].size ] == dsk then
twr_fr = 2
else
twr_fr = 3
end

towers[twr_fr].size = towers[twr_fr].size - 1

towers[twr_to].size = towers[twr_to].size + 1
towers[twr_to].elem[ towers[twr_to].size ] = dsk

print_towers()
end

return moves
end

function keep_playing()

while true do
io.write("TRY AGAIN (YES OR NO)? ")
local input = io.read("*line")

if input == "YES" or input == "yes" then
return true
elseif input == "NO" or input == "no" then
return false
else
print "'YES' OR 'NO' PLEASE"
end
end
end

function start_loop()

while true do
init_game()
print_towers()

local moves = game_loop()

--check ideal solution
if moves == (2^total_disks) - 1 then
print "CONGRATULATIONS!!"
end

print ( string.format("YOU HAVE PERFORMED THE TASK IN %d MOVES.\n", moves) )

if not keep_playing() then
break
end
end

print "\nTHANKS FOR THE GAME!"
end

start_loop()
59 changes: 59 additions & 0 deletions 91_Train/lua/train.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
print [[
TRAIN
CREATIVE COMPUTING MORRISTOWN, NEW JERSY
TIME - SPEED DISTANCE EXERCISE]]

math.randomseed(os.time())

local ERROR_MARGIN <const> = 5.0

function play()
local car_speed = 25*math.random() + 40--Between 40 and 64
local delta_time = 15*math.random() + 5--Between 5 and 19
local train_speed = 19*math.random() + 20--Between 20 and 38

print( string.format("\nA CAR TRAVELING AT %u MPH CAN MAKE A CERTAIN TRIP IN %u HOURS LESS THAN A TRAIN TRAVELING AT %u MPH.", car_speed, delta_time, train_speed) )

local try = true
local input
while try do
io.write("HOW LONG DOES THE TRIP TAKE BY CAR? ")
input = io.read("n")
if input == nil then
print("<!>PLEASE INSERT A NUMBER<!>")
else
try = false
end
io.read()
end

local car_time = delta_time * train_speed / (car_speed - train_speed)
local percent = ( math.abs(car_time-input) * 100 / car_time + .5)

if percent > ERROR_MARGIN then
print( string.format("SORRY. YOU WERE OFF BY %f PERCENT.", percent) )
else
print( string.format("GOOD! ANSWER WITHIN %f PERCENT.", percent) )
end

print( string.format("CORRECT ANSWER IS %f HOURS.", car_time) )
end

function game_loop()
local keep_playing = true
while keep_playing do
play()
io.write("\nANOTHER PROBLEM (YES OR NO)? ")
answer = io.read("l")

if not (answer == "YES" or answer == "Y" or answer == "yes" or answer == "y") then
keep_playing = false
end
end

end

game_loop()

0 comments on commit e8fb61f

Please sign in to comment.