ruby interview question - ruby

I got this question in a previous interview and couldnt do it , any idea?
What does this do:
`$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,#%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`

This is Perl code that prints out "Just another Perl hacker."
While most of the $_, $=, etc. variables are available in Ruby as well, the presence of statements such as $,++ indicate Perl, which actually has pre- and post-increment operators, unlike Ruby.
I went in with Vim and replaced all the symbols with their English equivalent. I munged something up since the output is now "Just another Per hacker" (missing the L on Perl), but here's what I came up with:
use English;
`$FORMAT_LINES_PER_PAGE`;
$ARG=\%!;($ARG)=/(.)/;$FORMAT_LINES_PER_PAGE=++$OUTPUT_AUTOFLUSH;
($INPUT_LINE_NUMBER,$/,$OUTPUT_FIELD_SEPARATOR,$OUTPUT_RECORD_SEPARATOR,$LIST_SEPARATOR,$SUBSCRIPT_SEPARATOR,$FORMAT_TOP_NAME,$OFMT,$FORMAT_NAME,$MULTILINE_MATCHING,$FORMAT_LINE_BREAK_CHARACTERS,#%)=(
$!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$LIST_SEPARATOR),$FORMAT_LINES_PER_PAGE++;
$INPUT_LINE_NUMBER++;
$INPUT_LINE_NUMBER++; $ARG++;$ARG++;
($ARG,$OUTPUT_RECORD_SEPARATOR,$OUTPUT_FIELD_SEPARATOR)=($FORMAT_NAME.$LIST_SEPARATOR."$SUBSCRIPT_SEPARATOR$/$FORMAT_PAGE_NUMBER[$CHILD_ERROR]$ARG$OUTPUT_RECORD_SEPARATOR$OUTPUT_FIELD_SEPARATOR$FORMAT_LINE_BREAK_CHARACTERS$FORMAT_PAGE_NUMBER[$CHILD_ERROR]",$LIST_SEPARATOR&$FORMAT_NAME,$OFMT,);
$OUTPUT_FIELD_SEPARATOR++ ;
$OUTPUT_FIELD_SEPARATOR++;
$FORMAT_TOP_NAME|=$LIST_SEPARATOR;
`$ARG$OUTPUT_RECORD_SEPARATOR$OUTPUT_FIELD_SEPARATOR$/$FORMAT_LINE_BREAK_CHARACTERS$SUBSCRIPT_SEPARATOR$FORMAT_NAME$MULTILINE_MATCHING$FORMAT_PAGE_NUMBER[$CHILD_ERROR]$INPUT_LINE_NUMBER$FORMAT_NAME$MULTILINE_MATCHING${#}$FORMAT_PAGE_NUMBER[$CHILD_ERROR]$SUBSCRIPT_SEPARATOR$OUTPUT_RECORD_SEPARATOR$LIST_SEPARATOR$FORMAT_TOP_NAME$FORMAT_NAME$MULTILINE_MATCHING.>&$FORMAT_LINES_PER_PAGE`

Here, I changed all the special Ruby globals into single-letter variables and inserted some whitespace:
`a`
n = \%!
(n) = /(.)/
a = ++o
(b, c, d, f, e, g, h, i, j, k, l, #%) = (m =~ /(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/, e), a++
b++
b++
n++
n++
(n, f, d) = (j . e . "gcp[q]nfdlp[q]", e & j, i,)
d++
d++
h |= e
`nfdclgjkp[q]bjk${#}p[q]gfehjk.>&a`
Whoever wrote this doesn't understand Ruby. There's no increment operator in Ruby. Tokens like \%! and #% mean nothing in Ruby. You can't interpolate variables, even global variables, in strings or backquoted commands, as in "$=". The dot . is not a concatenation operator in Ruby. I don't think this is Ruby. It's like a hybrid of languages.

I am not a Ruby expert by any means by the first step should be make it into a format you can read. I broke it down by line.
`$=`;
$_=\%!;
($_)=/(.)/;
$==++$|;
($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,#%)=($!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
$_++;
$_++;
($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);
$,++;
$,++;
$^|=$";
`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
I cheated and tried to run it, and it doesn't work. I get an unexpected null error.
Don't feel bad if you can't do this. This seems pointless. Programming questions should try to test your skills not test you on something that if somebody is really using it would mean there application would be really bad.

This looks closer to Perl, to be honest, but in any case pretty nonsensical.

Not related to Ruby I think, above encoded message is given at https://en.wikipedia.org/wiki/Just_another_Perl_hacker with the help of only punctuation. Another one is also provided there.
''=~('(?{'.('-)#.)#_*([]#!#/)(#)#-#),#(##+#)'
^'][)#]`}`]()`#.#]#%[`}%[#`#!##%[').',"})')

Related

Filter an collection of tuples

I'm playing with iterables and comprehension in Julia and tried to code simple problem: find all pairs of numbers less then 10 whose product is less then 10. This was my first try:
solution = filter((a,b)->a*b<10, product(1:10, 1:10))
collect(solution)
but I got error "wrong number of arguments". This is kind of expected because anonymous function inside filter expects two arguments but it gets one tuple.
I know I can do
solution = filter(p->p[1]*p[2]<10, product(1:10, 1:10))
but it doesn't look nice as the one above. Is there a way I can tell that (a,b) is argument of type tuple and use something similar to syntax in first example?
I don't think there's a way to do exactly as you'd like, but here are some alternatives you could consider for the anonymous function:
x->let (a,b)=x; a*b<10 end
x->((a,b)=x; a*b<10)
These can of course be made into macros if you like:
macro tup(ex)
#assert ex.head == :(->)
#assert ex.args[1].head == :tuple
arg = gensym()
quote
$arg -> ( $(ex.args[1]) = $arg; $(ex.args[2]) )
end
end
Then #tup (a, b) -> a * b < 10 will do as you like.
Metaprogramming in Julia is pretty useful and common for situations where you are doing something over and over and would like specialized syntax for it. But I would avoid this kind of metaprogramming if this were a one-off thing, because adding new syntax means learning new syntax and makes code harder to read.

Ruby String#unpack

I have a packed string of 3 strings that is composed in a way so that I have an integer, specifying the byte length of the next item and then that item's bytes and then the next item's bytesize, etc. as if somebody did:
[a.bytesize, a, b.bytesize, b, c.bytesize, c].pack("na*na*na*")
How can I properly unpack that in a simple manner? The Perl solution to this problem was:
my($a, $b, $c) = unpack("(n/a*)3", $data)
For ruby, which apparently doesn't support '/' and parentheses in unpack, I'm using something like:
vals = []
3.times do
size = data.unpack("n").first
data.slice!(0, 2)
vals << data.unpack("a#{size}").first
data.slice!(0, size)
end
Is there an easier way to this?
IMHO it is not as easy as in PERL, but this is some solution I can suggest.
unpacked = []
a, b, c = *unpacked << data.slice!(0, data.slice!(0, 2).unpack('S>').first) \
until data.empty?
I don't see a way to do this as easily as the Perl solution (and agree it would be good to file a feature request to get that added in Ruby's pack/unpack implementation), but I could at least provide the solution in fewer lines if that helps:
vals = []
until data.empty?
vals << data.slice!(0, data.slice!(0,2).unpack('n').first.to_i).unpack("a*").first
end
If you need any serious binary data processing, there's a gem for it:
http://bindata.rubyforge.org/
I think you should use it, instead of forging unpacks un running loops.
You can of course file a feature request and wait for it to be implemented,
but I suggest you use bindata gem instead, which is a much more robust solution IMO.

How do I define a new numeric constant in Mathematica?

What is the best way to define a numerical constant in Mathematica?
For example, say I want g to be the approximate acceleration due to gravity on the surface of the Earth. I give it a numerical value (in m/s^2), tell Mathematica it's numeric, positive and a constant using
Unprotect[g];
ClearAll[g]
N[g] = 9.81;
NumericQ[g] ^= True;
Positive[g] ^= True;
SetAttributes[g, Constant];
Protect[g];
Then I can use it as a symbol in symbolic calculations that will automatically evaluate to 9.81 when numerical results are called for. For example 1.0 g evaluates to 9.81.
This does not seem as well tied into Mathematica as built in numerical constants. For example Pi > 0 will evaluate to True, but g > 0 will not. (I could add g > 0 to the global $Assumptions but even then I need a call to Simplify for it to take effect.)
Also, Positive[g] returns True, but Positive[g^2] does not evaluate - compare this with the equivalent statements using Pi.
So my question is, what else should I do to define a numerical constant? What other attributes/properties can be set? Is there an easier way to go about this? Etc...
I'd recommend using a zero-argument "function". That way it can be given both the NumericFunction attribute and a numeric evaluation rule. that latter is important for predicates such as Positive.
SetAttributes[gravUnit, NumericFunction]
N[gravUnit[], prec_: $MachinePrecision] := N[981/100, prec]
In[121]:= NumericQ[gravitUnit[]]
Out[121]= True
In[122]:= Positive[gravUnit[]^2 - 30]
Out[122]= True
Daniel Lichtblau
May be I am naive, but to my mind your definitions are a good start. Things like g > 0->True can be added via UpValues. For Positive[g^2] to return True, you probably have to overload Positive, because of the depth-1 limitation for UpValues. Generally, I think the exact set of auto-evaluated expressions involving a constant is a moving target, even for built-in constants. In other words, those extra built-in rules seem to be determined from convenience and frequent uses, on a case-by-case basis, rather than from the first principles. I would just add new rules as you go, whenever you feel that you need them. You probably can not expect your constants to be as well integrated in the system as built-ins, but I think you can get pretty close. You will probably have to overload a number of built-in functions on these symbols, but again, which ones those will be, will depend on what you need from your symbol.
EDIT
I was hesitating to include this, since the code below is a hack, but it may be useful in some circumstances. Here is the code:
Clear[evalFunction];
evalFunction[fun_Symbol, HoldComplete[sym_Symbol]] := False;
Clear[defineAutoNValue];
defineAutoNValue[s_Symbol] :=
Module[{inSUpValue},
s /: expr : f_[left___, s, right___] :=
Block[{inSUpValue = True},
With[{stack = Stack[_]},
If[
expr === Unevaluated[expr] &&
(evalFunction[f, HoldComplete[s]] ||
MemberQ[
stack,
HoldForm[(op_Symbol /; evalFunction[op, HoldComplete[s]])
[___, x_ /; ! FreeQ[Unevaluated[x], HoldPattern#expr], ___]],
Infinity
]
),
f[left, N[s], right],
(* else *)
expr
]]] /; ! TrueQ[inSUpValue]];
ClearAll[substituteNumeric];
SetAttributes[substituteNumeric, HoldFirst];
substituteNumeric[code_, rules : {(_Symbol :> {__Symbol}) ..}] :=
Internal`InheritedBlock[{evalFunction},
MapThread[
Map[Function[f, evalFunction[f, HoldComplete[#]] = True], #2] &,
Transpose[List ### rules]
];
code]
With this, you may enable a symbol to auto-substitute its numerical value in places where we indicate some some functions surrounding those function calls may benefit from it. Here is an example:
ClearAll[g, f];
SetAttributes[g, Constant];
N[g] = 9.81;
NumericQ[g] ^= True;
defineAutoNValue[g];
f[g] := "Do something with g";
Here we will try to compute some expressions involving g, first normally:
In[391]:= {f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,g<0,g^2+a^2<0}
Out[391]= {Do something with g,g^2,g^2>0,2 g,Positive[1+2 g],
Positive[-a+2 g],a^2+g^2,a^2+g^2>0,g<0,a^2+g^2<0}
And now inside our wrapper (the second argument gives a list of rules, to indicate for which symbols which functions, when wrapped around the code containing those symbols, should lead to those symbols being replaced with their numerical values):
In[392]:=
substituteNumeric[{f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,
g<0,g^2+a^2<0},
{g:>{Positive,Negative,Greater}}]
Out[392]= {Do something with g,g^2,True,2 g,True,Positive[19.62\[VeryThinSpace]-a],
a^2+g^2,96.2361\[VeryThinSpace]+a^2>0,g<0,a^2+g^2<0}
Since the above is a hack, I can not guarantee anything about it. It may be useful in some cases, but that must be decided on a case-by-case basis.
You may want to consider working with units rather than just constants. There are a few options available in Mathematica
Units
Automatic Units
Designer units
There are quite a few technical issues and subtleties about working with units. I found the backgrounder at Designer Units very useful. There are also some interesting discussions on MathGroup. (e.g. here).

Converting this into a Ruby one-liner

I'm currently trying to making my obfuscated, short mandelbrot set code into a one-liner, but I'm having a lot of trouble in doing so. \
It was originally written in Python, but due to Python's limitations, I could not compress the code to one line. So now I'm going to try Ruby. I'm familiar with the language, but I'm not very skilled in using blocks - which is where I am having the issue.
Anyway, the code I want to "convert" is
for q in range(801):
if q%40==0:print s;s=''
i,k=0,0
while(abs(k)<2*(i<15)):k,i=k**2+complex(q%40*.075-2,q/40*-.1+1),i+1
s+=h[i/3]
Which I've attempted to rewrite in Ruby...
h,s='.;*&8#',''
0.upto(800).each {|q|
if !q%40
s=''
p s
end
i,k=0,0
while(k.abs<2*(i<15))
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1
end
s+=h[i/3]
}
Which throws the error
Line 2:in `upto': no block given (LocalJumpError)
from t.rb:2
After sorting this out, I'd like to shorten it further to one line. Which I've started here...
h,s='.;*&8#','';0.upto(800).each {|q| if !q%40 then s='';p s end;i,k=0,0;while(k.abs<2*(i<15))do k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1 end}
But anyway, I'm just doing this for fun, and hoping to learn a little more Ruby in the process. So if anyone can explain to me what is throw these errors, that would be great.
require 'complex'
h,s='.;*&8#',''
0.upto(800).each {|q|
if q%40 == 0
p s
s=''
end
i,k=0,0
while(k.abs<2 && (i<15))
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1
end
s+=h[i/3, 1]
}
Issues I dealt with:
Ruby conditionals return boolean values, not 1 or 0, and ! has a high priority
You were clobbering s before printing it
To work on 1.8.x and 1.9.x you need to index strings with [x, 1]
And here it is rearranged a little as a better starting point for a one-liner:
require 'complex'
h,s='.;*&8#',''
800.times { |q|
(p s; s='') if q%40 == 0
i,k=0,0
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1 while k.abs<2 && i<15
s+=h[i/3, 1]
}
Fist, get rid of the each, the block should go with upto. Once you did that, you'll get another error: undefined method '%' for false:FalseClass. This is because of !q%40, since precedence will first do the logical negation of q (anything but nil and false are true) and then try to evaluate false%40. Also you seem to assume that a zero would evaluate to false, which it doesn't. Then the next problem will be in the condition of your while loop, since k.abs<2 as well as i<15 evaluate to boolen values (`*': true can't be coerced into Fixnum). This should get you started...
Here's a multi-line version; feel free to put it all on one line:
h,s='.;*&8#','';
0.upto(800).each { |q|
(puts s;s='') if q%40==0;
i,k=0,0;
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1 while k.abs<2*(i<15?1:0);
s+=h[i/3]
}

Evaluation in Scheme

ok, i have this problem here. i was asked to write a function in Scheme, that takes an "environment", and an expression and it returns the value of this expression, for the variable bindings found in the enviroment.
and a definition of a boolean expression is this according to the question below.
edit sorry my question is what does it mean by "it takes an environment" as an argument and what exactly does the function need to do?
evaluate for example "T OR F" and return "F" ???
"<expr> ::= <boolean>
|<variable>
|(not <expr>)
|(or <expr> <expr>)
|(and <expr> <expr>"
An environment is basically a dictionary of variable names to values. So given the environment
var1 = #t
var2 = #f
var3 = #t
and an expression
(or var2 (and T (or var1 var3)))
You would need to substitute the given values of var1, var2, and var3 into the expression, and then evaluate the expression.
Your function will probably be given the environment as some sort of Lisp structure, probably an alist, as one of its parameters.
From what I can determine you have been asked to implement eval.
So you should for starters have:
(define (eval expr env)
... )
where expr can be any of the forms you mention and env would keep the symbols defined (possibly a association list).
The first 2 cases are relatively trivial, the 3rd one, application of the not procedure should also be easy, given not will be in the environment (eg (list (cons 'not not))).
But the harder part lies in the last 2. Both of those are macros, and will require some expansion. The standard definitions/expansions of those should have been given to you. Once expanded, you can simply call eval recursively to evaluate the expanded expression.
Good luck :)
Edit:
Both and and or expands to if, so you will need to implement that too.
By "environment" they probably mean the equivalent of "scope" in other languages. Consider the following C fragment:
if (7 < 100)
{
int j = 2;
if (j < 4)
{
int k = 7, j = 14;
printf("k = %d, j = %d\n", k, j);
}
}
Note that in the outer scope (marked out by the outer set of braces) the only variable is j. In the inner scope there is a new j and a k. So there are three variables here, the outer j, and the inner j and k.
One way of implementing this is to define a scope to be a list of "environments". As you enter a new block, you put another "environment" in your list. When looking up variables by name, you look first in the most recently added "environment". If it isn't found there, you move along the list of environments to the next and look there, and so on.
An "environment" itself is often just a list of pairs, matching up names of variables with values. So it sounds like you are being asked to pass such a list to your function, each pair giving the symbol for a boolean variable and its value. Based on which variables are currently "in scope", you fetch their values out of the environment and use them in the expressions you are evaluating (according to that expression grammar you've been given).
In your case, it sounds like you aren't being asked to worry about which enviroments are in scope. You just have one environment, i.e. one list of pairs.
Sounds like a fair bit of work, good luck!
One reference that might help is:
http://michaux.ca/articles/scheme-from-scratch-bootstrap-v0_9-environments

Resources