Julia: define method for custom type - methods

I apologize if this has been answered before, I didn't find a straight answer for this among my search results.
I'm going through "Learn Julia The Hardway" and I can't really find where's the difference in my code vs the example in the book. Whenever I run it I get the following error:
TypeError: in Type{...} expression, expected UnionAll, got a value of type typeof(+)
Here's the code:
struct LSD
pounds::Int
shillings::Int
pence::Int
function LSD(l,s,d)
if l<0 || s<0 || d<0
error("No negative numbers please, we're british")
end
if d>12 error("That's too many pence") end
if s>20 error("That's too many shillings") end
new(l,s,d)
end
end
import Base.+
function +{LSD}(a::LSD, b::LSD)
pence_s = a.pence + b.pence
shillings_s = a.shillings + b.shillings
pounds_s = a.pounds + b.pounds
pences_subtotal = pence_s + shillings_s*12 + pounds_s*240
(pounds, balance) = divrem(pences_subtotal,240)
(shillings, pence) = divrem(balance,12)
LSD(pounds, shillings, pence)
end
Another quick question, I haven't got yet to the functions chapter, but it catches my attention that there is no "return" at the end of the functions, I'm guessing that if it isn't stated a function will return the last evaluated value, am I right?

This appears to be using very old Julia syntax (I think from version 0.6). I think you just want function +(a::LSD, b::LSD)

Related

Extending (Monkey Patching) a Binary Search for Array Class and Syntactic Sugar

I've been studying a few searching algorithms and my last problem comes down to binary searching. I watched a few youtube videos to understand the concept and then tried to solve the problem, but keep getting an endless loop error. I've looked through stack overflow, and reddit, and wherever Google would lead me, but I can't quite find a solution that fits my method of coding. Also, please excuse the term 'monkey patching', it's been brought to my attention that the technical term is called 'extending' so the fault lies on my instructors for teaching it to us as 'monkey patching'.
Here's my code:
class Array
def my_bsearch(target)
return nil if self.empty?
middle_idx = self.length/2
left = self.take(middle_idx)
right = self.drop(middle_idx + 1)
return middle_idx if self[middle_idx] == target
until self[middle_idx] == target || self.nil? == nil
if self[middle_idx] < target
right.my_bsearch(target)
elsif self[middle_idx] > target
left.my_bsearch(target)
end
end
end
end
I have a solution, but I don't want to just memorize it-- and I'm having trouble understanding it; as I'm trying to translate it, learn from it, and implement what I'm missing into my own code.
class Array
def my_bsearch(target)
return nil if size == 0
mid = size/2
case self[mid] <=> target
when 0
return mid
when 1
return self.take(mid).my_bsearch(target)
else
search_res = self.drop(mid+1).my_bsearch(target)
search_res.nil? ? nil : mid + 1 + search_res
end
end
end
I guess I understand case/when despite not use to using it. I've tried following it with debugger, but I think I'm hung up on what's going on in the ELSE section. The syntactic sugar, while making this obviously more concise than my logic, isn't straight-forward/clean to someone of my ruby literacy level. So, yeah, my ignorance is most of the problem I guess.
Is there someone who is a little more literate, and patient, able to help me break this down into something I can understand a bit better so I can learn from this?
First, take and drop have sufficiently similar interfaces that you don't actually want your + 1 for drop. It will disregard one element in the array if you do.
Next, self.nil? will always be false (and never nil) for instances of this class. In fact, .nil? is a method exactly to avoid having to ever compare against nil with ==.
You want self.empty?. Furthermore, with the exception of setters, in Ruby messages are sent to self by default. In other words, the only time self. is a useful prefix is when the message ends in = and operates as an lvalue, as in self.instance_var = 'a constant', since without the self., the tokens instance_var = would be interpreted as a local variable rather than an instance variable setting. That's not the case here, so empty? will suffice just as well as self.empty?
So I figured it out, and I decided to answer my own post in hopes to help someone else out if they run into this issue.
So, if I have an Array and the target is the middle_element, then it will report middle_element_idx. That's fine. What if the target is less than middle_element? It recursively searches the left-side of the original Array. When it finds it, it reports the left_side_idx. There's no problem with that because elements in an array are sequentially counted left to right. So, it starts at 0 and goes up.
But what if the target is on the right side of the middle element?
Well, searching for the right side is easy. Relatively the same logic as searching left. Done recursively. And it will return a target_idx if it's found on that right side --however that's the target's idx as it was found in the right-side array! So, you need to take that returned target_idx and add 1 to it and the original middle_element_idx. See below:
def my_bsearch(target)
return nil if self.empty?
middle_idx = self.length/2
left = self.take(middle_idx)
right = self.drop(middle_idx + 1)
if self[middle_idx] == target
return middle_idx
elsif self[middle_idx] > target
return left.my_bsearch(target)
else
searched_right_side = 1 + right.my_bsearch(target)
return nil if searched_right_side.nil? == true
return searched_right_side + middle_idx
end
end
end
Notice how many more lines this solution is? The spaceship operator used in conjunction with case/when and a ternary method will reduce the number of lines significantly.
Based on suggestions/feedback from Tim, I updated it to:
def my_bsearch(target)
return nil if empty?
middle_idx = self.length/2
left = self.take(middle_idx)
right = self.drop(middle_idx)
if self[middle_idx] == target
return middle_idx
elsif self[middle_idx] > target
return left.my_bsearch(target)
else
searched_right_side = right.my_bsearch(target)
return nil if searched_right_side.nil?
return searched_right_side + middle_idx
end
end
end

What am I doing wrong with this simple If function in ruby

I have been trying to teach myself to code and have gravitated towards Ruby.
Upon working on if functions I have come across this problem where even if the user input is == to the answer variable it still comes back as false in the if function. It will not come back as true
I can get it to work if it is an Integer, but for some reason it always returns false when having a string. Tried to convert is as well but can not figure it out.
Thank you for any help.
puts("For each question select A, B, or C")
puts("What is the capital of Kentucky?")
puts()
puts("A. Louisville")
puts("B. Frankfort")
puts("C. Bardstown")
puts()
answer = String("B")
text = gets()
puts()
if text == answer
puts("correct")
else
puts("incorrect")
puts("The correct answer was " + answer + ".")
end
There is an additional method you can call when declaring the "text" variable that will solve this.
The method you used preserves a line break at the end when you press enter to submit an answer so it will never actually correspond to the answer. To remove the line break use the "chomp" method.
text = gets.chomp
Hope this helped. Good luck.

What is the return type of my VBScript function?

This question is mostly out of interest to understand the functionality of VBScript better. I recognize that I can simply do some casting to know what to expect from my code, but in my situation I want to understand why casting, or any "workaround", is needed. For simplicity, here's the basic idea of my code:
variable1 = 1
Public Function findSomethingInATextString(par1, par2)
[...searching with a Do Until loop code here...]
Result = 1
If([par2 is found in par1]) Then
Result = 0
End If
Return Result
End Function
variable1 = findSomethingInATextString("Hello World", "Hello")
When I run this I get a Type Mismatch error. I don't understand why that's the case. variable1 is an integer and findSomethingInAString() returns an integer. They appear to be the same data type.
I'm working in a restricted environment where I can't do much debugging (it's painfully slow to code in this program...). So at the moment I'm unable to say what data type this is coming out as - I just know that it's apparently not integer.
After all that, and to make sure my question is clear, I'm intrigued to know what the return type of my function is (if someone happens to know), but my real question is: Why isn't the return type matching with variable1?
Use the minimal script
Return
Output
cscript 36633603.vbs
...36633603.vbs(1, 1) Microsoft VBScript runtime error: Type mismatch: 'return'
to prove to yourself, that just mentioning return in a VBScript will throw a type mismatch error.
Believe JosefZ's comment that VBScript returns function values by assigning to the function's name. Better: Read the docs (before you try to write code).
Evidence:
Function f1()
f1 = 1
End Function
WScript.Echo f1(), TypeName(f1())
Output:
cscript 36633603.vbs
1 Integer

Returning multiple ints and passing them as multiple arguements in Lua

I have a function that takes a variable amount of ints as arguments.
thisFunction(1,1,1,2,2,2,2,3,4,4,7,4,2)
this function was given in a framework and I'd rather not change the code of the function or the .lua it is from. So I want a function that repeats a number for me a certain amount of times so this is less repetitive. Something that could work like this and achieve what was done above
thisFunction(repeatNum(1,3),repeatNum(2,4),3,repeatNum(4,2),7,4,2)
is this possible in Lua? I'm even comfortable with something like this:
thisFunction(repeatNum(1,3,2,4,3,1,4,2,7,1,4,1,2,1))
I think you're stuck with something along the lines of your second proposed solution, i.e.
thisFunction(repeatNum(1,3,2,4,3,1,4,2,7,1,4,1,2,1))
because if you use a function that returns multiple values in the middle of a list, it's adjusted so that it only returns one value. However, at the end of a list, the function does not have its return values adjusted.
You can code repeatNum as follows. It's not optimized and there's no error-checking. This works in Lua 5.1. If you're using 5.2, you'll need to make adjustments.
function repeatNum(...)
local results = {}
local n = #{...}
for i = 1,n,2 do
local val = select(i, ...)
local reps = select(i+1, ...)
for j = 1,reps do
table.insert(results, val)
end
end
return unpack(results)
end
I don't have 5.2 installed on this computer, but I believe the only change you need is to replace unpack with table.unpack.
I realise this question has been answered, but I wondered from a readability point of view if using tables to mark the repeats would be clearer, of course it's probably far less efficient.
function repeatnum(...)
local i = 0
local t = {...}
local tblO = {}
for j,v in ipairs(t) do
if type(v) == 'table' then
for k = 1,v[2] do
i = i + 1
tblO[i] = v[1]
end
else
i = i + 1
tblO[i] = v
end
end
return unpack(tblO)
end
print(repeatnum({1,3},{2,4},3,{4,2},7,4,2))

problems implementing negamax for tic-tac-toe in ruby

I'm banging my head against the wall trying to implement negamax for tic-tac-toe
def negamax(board_obj, mark, depth)
if board_obj.game_over?
return value(board_obj)
else
max = -1.0/0 # negative infinity
if mark == #mark
next_mark = #opponent_mark
else
next_mark = #mark
end
board_obj.empty_squares.each do |square|
board_obj[square] = mark
x = -negamax(board_obj, next_mark, depth + 1)
board_obj[square] = ' '
if x > max
max = x
#scores << x
#best_move = square if depth == 1
end
end
return max
end
end
# determines value of final board state
def value(board_obj)
if board_obj.mark_win?(#mark)
return 1
elsif board_obj.mark_win?(#opponent_mark)
return -1
else
return 0
end
end
the rest of the code is here: https://github.com/dave-maldonado/tic-tac-doh/blob/AI/tic-tac-doh.rb
It does produce a result but the AI is easily beat so I know something's wrong, any help
is appreciated!
The problem is that value needs to be relative to the mark in the current execution of negamax rather than always relative to the computer. If you pass in the mark argument to value from negamax with the following modified definition for value, you'll get the right results:
def value(board_obj, mark)
if board_obj.mark_win?(mark)
return 1
elsif board_obj.mark_win?(mark == 'X' ? 'O' : 'X')
return -1
else
return 0
end
end
That is, the first two lines of the negamax body need to be:
if board_obj.game_over?
return value(board_obj, mark)
That said, this overall program leaves an awful lot to be desired relative to Ruby, good design principles, etc (no offense intended). Now that you have it running, you might want to head over to the Code Review SE for some feedback. :-) And while it's too late to use TDD ;-), it would also be a good one to put "under test".
Also, please understand that per one of the other comments, this is not a kind of question that you'll typically get an answer to here at SO. I don't even know if this question will survive the review process without getting deleted. I worked on it for a variety of personal reasons.
Update: Looking at your reference implementation, you'll note that the negamax code includes the expression sign[color]*Analysis(b). It's that sign[color] that you were missing, effectively.

Resources