Game programmer Interview question

Started by
48 comments, last by jay_porter 15 years, 3 months ago
let find numbers t =  let p a b c = c^string_of_int a^b in  let n = length numbers in  let v c = code c - code '0' in  let l = v numbers.[n-1] in  let rec aux sum prod cat k s i =    let tot = sum + prod * cat in    if tot > t then None else if i < 0 then      if tot = t then Some (s "") else None    else let c = v numbers. in    fold_left (fun r f -> if r <> None then r else      match f (i-1) with None -> None | Some x -> Some (s x)) None [      aux sum  prod         (c*k + cat) (10*k) (p c "" ) ;      aux sum (prod * cat)   c           10    (p c "*") ;      aux tot  1             c           10    (p c "+") ]  in aux 0 1 l 10 (p l "") (n-2)


This is an almost brute-force algorithm (the only pruning done here is to stop if the total found so far exceeds the expected total). This takes about 4ms to solve the "1231231234" = 11353 problem, and took me about 10 minutes to write.
Advertisement
are there books that teach you this kind of stuff...or at least close to teaching how to solve this kind of stuff??(you know what i mean,its hard to put into words)

what do you recommend??
Quote:Original post by Skeezix
are there books that teach you this kind of stuff...or at least close to teaching how to solve this kind of stuff??(you know what i mean,its hard to put into words)

what do you recommend??


Experience unfortunately...

Cheers,MartinIf I've helped you, a rating++ would be appreciated
Yes, for instance Book and Book. Also peruse all parts of wikipedia related to algorithms.

The code I used was merely a brute-force search (try all combinations one after another) with implicit stack-based memoization (a consequence of the recursive approach, not of the algorithm itself) and a clever closure-based trick for outputting the result once found.
Quote:Original post by ToohrVyk
let find numbers t =  let p a b c = c^string_of_int a^b in  let n = length numbers in  let v c = code c - code '0' in  let l = v numbers.[n-1] in  let rec aux sum prod cat k s i =    let tot = sum + prod * cat in    if tot > t then None else if i < 0 then      if tot = t then Some (s "") else None    else let c = v numbers. in    fold_left (fun r f -> if r <> None then r else      match f (i-1) with None -> None | Some x -> Some (s x)) None [      aux sum  prod         (c*k + cat) (10*k) (p c "" ) ;      aux sum (prod * cat)   c           10    (p c "*") ;      aux tot  1             c           10    (p c "+") ]  in aux 0 1 l 10 (p l "") (n-2)

I know it would probably be a pain, but could you explain this pseudocode? I'm having a hard time understanding it, especially the way you use "let" to assign to several values at once (at least, that what it looks like to me [lol] ).

Interesting question. I'm going through some rigorous interviews now too, and I find the coding/algorithm questions to be a bit frustrating sometimes, especially when you only have 10 minutes to figure them out and really don't have any experience with the subject matter. And implementing sorts is a pain. [lol]
Quote:Original post by GenuineXP
I know it would probably be a pain, but could you explain this pseudocode? I'm having a hard time understanding it, especially the way you use "let" to assign to several values at once (at least, that what it looks like to me [lol] ).
Am not... Multiple assignment happens using let a,b = 1, 2, wheread let a b = ... defines a function 'a' with a parameter 'b'.The complete explanation:

(* Define a function "find" with parameters "numbers"   (which is the string we are analysing) and "t" (which is the   target number *)let find numbers t =  (* A printing function. Here, p 3 "*" "1+2+" outputs "1+2+3*". *)  let p a b c = c^string_of_int a^b in  (* Duh. *)  let n = length numbers in  (* Convert a character to its integer representation by transforming it     to its ASCII code and substracting the ASCII code of '0'. *)  let v c = code c - code '0' in  (* The last character in the string. This is our starting value, since     we process the string right-to-left to make parsing easier. *)  let l = v numbers.[n-1] in  (* The recursive function which processes everything. In order to evaluate     the value computed so far without having to build and parse a string, it     implements a recursive descent parser (here, "sum", "prod", "cat" and "k"     are the unrolled stack contents for grammar rules "+", "*" and "").      Parameter 's' represents the previously applied operation: it's used for     printing the result once it is found. Parameter 'i' is the current index     within the string. *)  let rec aux sum prod cat k s i =    (* Fold the stack to simulate receiving an EOF right now. *)    let tot = sum + prod * cat in    (* Overflow heuristic. If the sum so far (which can never decrease)           exceeds the target, we have to stop and backtrack. *)    if sum > t then None     (* We've reached the beginning of the stream, so there's nothing       else to do. Check if the target is reached. *)    else if i < 0 then            (* If we reached the target, return a "do nothing" string because         we're at the beginning of the string with no characters.*)      if tot = t then Some (s "") else None    (* We have to read another character. This computes its value. *)    else let c = v numbers. in    (* This code attempts concatenation, multiplication and addition.        Since they all behave the same, we just put them in a list of functions        to be called, then call them until we have a solution. *)    fold_left       (* This function receives parameter 'r' representing the results         so far, and 'f' representing the next function we can try. If          'r' is a valid result, we return it. Otherwise, we look to see         if 'f' finds a solution (decreasing the index as this happens).          If a solution is found, we print the previous character and return         it. *)      (fun r f -> if r <> None then r else        match f (i-1) with None -> None | Some x -> Some (s x)) None [      (* First try: concatenation. This multiplies the character by         the current multiplier, then multiplies the multiplier by 10 *)      aux sum  prod         (c*k + cat) (10*k) (p c "" ) ;      (* Second try: multiplication. We go back once on the stack,          multiply the previous number with the multiplier, then push the         character on the stack as beginning a new number. *)      aux sum (prod * cat)   c           10    (p c "*") ;      (* Third try: addition. We go back twice on the stack and add         everything up, then push "1" as the "current product value"         and c as the "current number value". *)      aux tot  1             c           10    (p c "+") ]  (* We apply the recursive function, with a starting "current sum     value" of 0, a "current product value" of 1, and using the first      character as the "current number value". *)  in aux 0 1 l 10 (p l "") (n-2)
Project Euler contains a lot of problems like this. Good for practicing and fun. :)
Create-ivity - a game development blog Mouseover for more information.
I made a speedy algorithm that completely fails to respect order of operations. Alas. I'd have to modify it to recurse differently to keep those operations, which disallows a ton of the pruning that made it speedy. Too much work for someone else's interview [grin]


As an interesting note, this sort of thing is analogous to what my toy programming language does to convert a stream of tokens into an AST.
Hi all...
Thats a very good way to solve the problem...But they mentioned Ansi C is not a must is always preferable....So i thought indirectly they mean its must to do in C itself then c#
Quote:Original post by srikanthpv
Hi all...
Thats a very good way to solve the problem...But they mentioned Ansi C is not a must is always preferable....So i thought indirectly they mean its must to do in C itself then c#


I find it unlikely someone will provide a C solution.

The reason is quite simple. Anyone who has dealt with such interviews in the past knows that C is implied (ANSI compliance is rarely required as such). Sometimes, C++ is also acceptable, but additional language features are never required.

As such, posting a solution in another language is just fine with respect to solving the problem, but it prevents the situation where it's possible to just copy paste the solution, especially since this type of assignments can sometimes be given out freely with longer time to submit.

What I'm simply trying to say is, someone capable of solving the problem will be able to code it in any language. There's also even a string hint in this particular problem (target value is a number, "given a string" and "a function") that can be taken advantage of in C or C++. It hints that there's little need for auxiliary structures, some complex recursive parsers or some complex class hierarchies.

But this is definitely not a C language proficiency test.

This topic is closed to new replies.

Advertisement