Open Side Menu Go to the Top
Register
Interview  Test Questions Problems, Solutions, Links, Discussion Interview  Test Questions Problems, Solutions, Links, Discussion

09-22-2016 , 01:18 PM
Quote:
Originally Posted by candybar
I'm specifically objecting to you saying this is the right approach in C.
i stand by it still being easier to grok, but concede it's not idiomatic c and isn't appropriate for most C contexts
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:22 PM
Quote:
Originally Posted by candybar
I don't understand - reality is not a confounding variable. It's like saying that we should write everything in Esperanto because it is theoretically easier to understand, ignoring that 1000 times more people can read English.
you're painting an inaccurate picture here. my claim is the concepts in the rotation solution are closer to what a 4 year old could understand. try to see past the (slightly) obscure syntax and the word pipe to the natural concept being expressed so easily. and btw I could easily remove everything that's even slightly arcane but assumed the ppl here could handle a bit of compactness
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:36 PM
Quote:
Originally Posted by gaming_mouse
you're painting an inaccurate picture here. my claim is the concepts in the rotation solution are closer to what a 4 year old could understand.
But aren't the concepts in the "Move through the matrix solution" simpler?

If someone gives me a piece of paper with a matrix and says "Write the numbers down in the swirl pattern", my intuitive solution is to just leave the matrix alone and read along the edges. Maybe using my finger to move from one number to the next.

It isn't to rotate the paper around under my finger or anything.

Even in a CS context, it feels like the more intuitive thing is to navigate the data structure and not manipulate the data structure.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:41 PM
Quote:
Originally Posted by gaming_mouse
you're painting an inaccurate picture here. my claim is the concepts in the rotation solution are closer to what a 4 year old could understand.
We're programmers that need to deliver working solutions, not a 4-year old trying to understand how the world works. We very often have to understand precisely how something is implemented, not merely that it kind of looks like it's doing something. I dig into third-party library implementations all the time - we don't live in a world where abstractions can be trusted and interfaces define what implementations deliver.

Quote:
try to see past the (slightly) obscure syntax and the word pipe to the natural concept being expressed so easily. and btw I could easily remove everything that's even slightly arcane but assumed the ppl here could handle a bit of compactness
I personally don't have any problem with the code other than runtime complexity - it's very close to how I program in OCaml - but I don't think it's particularly easier to work with than simple solutions posted earlier. And if your code is substantially less efficient, it's probably not an objectively better solution unless it is unambiguously simpler, which I don't think it is. Again, I appreciate seeing your solution because it's awesome in its own way but I think the presentation of it as being objectively superior and capturing the essence of the problem is a little over the top.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:42 PM
Quote:
Originally Posted by jjshabado
But aren't the concepts in the "Move through the matrix solution" simpler?

If someone gives me a piece of paper with a matrix and says "Write the numbers down in the swirl pattern", my intuitive solution is to just leave the matrix alone and read along the edges. Maybe using my finger to move from one number to the next.

It isn't to rotate the paper around under my finger or anything.

Even in a CS context, it feels like the more intuitive thing is to navigate the data structure and not manipulate the data structure.
Might depend on whether you're visual thinker or not. I can't really grasp things unless I can visualize them. First thing I thought of was to rotate the array.

Actually the first thing I did was just solve the simple case of outputting the first row. Then I looked at that and said, what's the next step? At that point the simplest thing seemed to be to just rotate the matrix.

I guess my second pass - the muncher - is pretty similar to yours, except I just throw away the outer layers instead of trying to keep track of an index (which I agree could be not preferrable given the application). Again probably triggered by my preference for visual-thinking. Trying to keep track of stuff like moving around the matrix and keep track of the row/column always ends up confusing me way more than it should.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:45 PM
Quote:
Originally Posted by suzzer99
Might depend on whether you're visual or not. First thing I thought of was to rotate the array.

Actually the first thing I did was just solve the simple case of outputting the first row. Then I thought about what to do next and realized if I rotated the array I could just keep doing the same thing.
Yeah, I think this is true. Because to me the intuitive thing is to go write out the edges and then handle the inner matrix.

I'll say that I think this is why coding questions are so hard for interviewers to judge. Because clarity is important but subjective (in these cases, imo).

I've actually gotten to be much less caring about runtime efficiency and much more caring about: "Can this person understand a question and figure out a 'reasonable' way to solve it" and "Can this person write code that does the thing they want it to do".
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:46 PM
Quote:
Originally Posted by jjshabado
But aren't the concepts in the "Move through the matrix solution" simpler?

If someone gives me a piece of paper with a matrix and says "Write the numbers down in the swirl pattern", my intuitive solution is to just leave the matrix alone and read along the edges. Maybe using my finger to move from one number to the next.

It isn't to rotate the paper around under my finger or anything.

Even in a CS context, it feels like the more intuitive thing is to navigate the data structure and not manipulate the data structure.
Also, recursion is fairly unintuitive to most people. One thing I found surprising is that programmers can deal with higher-order functions much more easily than explicit recursion. Tons of people who have no problem using map/reduce/filter/etc are often more than a little uncomfortable with recursion. Not to mention that he's using an accumulator pattern to force his solution to be more loop-like (or tail-recursive), which is also not obvious.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:48 PM
Quote:
Originally Posted by jjshabado
But aren't the concepts in the "Move through the matrix solution" simpler?

If someone gives me a piece of paper with a matrix and says "Write the numbers down in the swirl pattern", my intuitive solution is to just leave the matrix alone and read along the edges. Maybe using my finger to move from one number to the next.

It isn't to rotate the paper around under my finger or anything.

Even in a CS context, it feels like the more intuitive thing is to navigate the data structure and not manipulate the data structure.
this is true but the tools we have for encoding that solution make it unreadable you might be able to write the follow the edges solution in something like J or APL naturally
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:50 PM
Quote:
Originally Posted by jjshabado
Yeah, I think this is true. Because to me the intuitive thing is to go write out the edges and then handle the inner matrix.

I'll say that I think this is why coding questions are so hard for interviewers to judge. Because clarity is important but subjective (in these cases, imo).

I've actually gotten to be much less caring about runtime efficiency and much more caring about: "Can this person understand a question and figure out a 'reasonable' way to solve it" and "Can this person write code that does the thing they want it to do".
FWIW - I would be absolutely thrilled with any of the answers given itt and immediately try to hire that person.

We literally get supposedly experienced javascript devs who get tripped up trying to create an NxN 2d array with incremented numbers in each square. Never mind putting a unique random #s from 1-N*N in each square. This has happened multiple times.

Also our bosses are so lazy we don't get that many interviewees. So as long as a candidate shows a pulse we give them a chance.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 01:52 PM
Quote:
Originally Posted by candybar
Also, recursion is fairly unintuitive to most people. One thing I found surprising is that programmers can deal with higher-order functions much more easily than explicit recursion. Tons of people who have no problem using map/reduce/filter/etc are often more than a little uncomfortable with recursion. Not to mention that he's using an accumulator pattern to force his solution to be more loop-like (or tail-recursive), which is also not obvious.
This is true. Recursion always taxes my brain more than other stuff. But in a fun way.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 02:00 PM
Quote:
Originally Posted by Barrin6
One week from today I have a technical phone interview where I will be writing code on a google doc. Recruiter sent me prep material telling me to basically learn everything about CS.

I am expecting an epic fail next week
To be honest, I always did fine on tests I didn't really give a **** about. This was a job I truly felt would be a "dream job" and totally choked under pressure. I gave too much of a ****, I guess.

Still licking my wounds on this one. Not sure how long it will take to recover from it since this was the apex of a very long search.

Quote:
Originally Posted by candybar
I think making this about functional vs procedural is a little off the mark though there's certainly correlation - functional code doesn't have to use a lot of abstractions and procedural code can use tons of abstractions that can make the resulting code hard to debug. I think you're also forgetting the context for this - I'm specifically objecting to you saying this is the right approach in C.
I think functional code has more abstractions since FP languages tend to have 15 primitives and very few built-in functions.

Technically, you can't have FP by reducing the matrix or rotating it, as that is mutation. The closest you can do is something that looks like this:

Code:
def swirl(m, row, column):
    row, column = go_right(m, row, column)
    row, column = go_down(m, row, column)
    row, column = go_left(m, row, column)
    row, column = go_up(m, row, column)
    swirl(m, row, column)

swirl(m, 0, 0)
That's always the silly part of reading about FP programs. "Oh, look! 6 LOC, but totally disregarding the other 4 functions that have 5 LOC each.

But ultimately, all the functions as shown here are pure, and therefore, under FP thought, easier to reason about and debug.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 02:13 PM
Quote:
Originally Posted by candybar
We're programmers that need to deliver working solutions, not a 4-year old trying to understand how the world works. We very often have to understand precisely how something is implemented, not merely that it kind of looks like it's doing something. I dig into third-party library implementations all the time - we don't live in a world where abstractions can be trusted and interfaces define what implementations deliver.
so i think we've covered most ground on this disagreement, i don't want you to think i'm being overly argumentative, but i want to respond to this last one because i deeply disagree with it, and since other people do read this thread, it's important to me that the counterpoint is totally clear, even if it's not accepted.

first, we ARE 4 years olds. i don't care if you have 5 math phds, complexity is still your biggest issue.

as for the second point, it's a straw man. i mean, your argument is that there's going to be a problem with ramda's "pipe" or "reverse" implementation? that's just... no. it's one step removed from worrying about your language's built in map implementation having a bug. for that matter, why are your for loops and i j indexes ok? how do you know the assembly is being properly generated? and even IF i grant you that it's a legitimate concern, the implementations are very short, it would be easy to debug. and if you're still worried, use a language that has built in support for these things. in any case, the answer is NOT to give up on using high-level constructs. they're the only hope we have.


Quote:
And if your code is substantially less efficient, it's probably not an objectively better solution unless it is unambiguously simpler, which I don't think it is. Again, I appreciate seeing your solution because it's awesome in its own way but I think the presentation of it as being objectively superior and capturing the essence of the problem is a little over the top.
i was being over-the-top on purpose, as i said. i am well aware the extreme emphasis on high-level concepts and brevity that I have is not universally accepted, and that lots of smart experienced programmer's hold more moderate or different views. but i really do stand by my position if you can achieve high-level clarity in your code, almost everything else becomes a trivial (or at least workmanlike) problem. but it's fine if we disagree
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 02:17 PM
Quote:
Originally Posted by daveT
That's always the silly part of reading about FP programs. "Oh, look! 6 LOC, but totally disregarding the other 4 functions that have 5 LOC each.
no, no, NO!

that's not silly, that's the point. the other 4 functions are just boring implementation detail, their purpose is clearly conveyed by their name, and you never you have to look at them unless you're debug something that involves them, but they're so simple and single-purpose that's rarely the case.

it's the whole essence of good programming. low-level detail is shuttled away, and everything at the high level is together, in one place, communicating what it does.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 05:16 PM
Quote:
Originally Posted by gaming_mouse

as for the second point, it's a straw man. i mean, your argument is that there's going to be a problem with ramda's "pipe" or "reverse" implementation? that's just... no. it's one step removed from worrying about your language's built in map implementation having a bug. for that matter, why are your for loops and i j indexes ok? how do you know the assembly is being properly generated? and even IF i grant you that it's a legitimate concern, the implementations are very short, it would be easy to debug. and if you're still worried, use a language that has built in support for these things. in any case, the answer is NOT to give up on using high-level constructs. they're the only hope we have.
I think candybar is more worried about the runtime complexity being obfuscated by those types of functions than bugs in their implementations.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 05:23 PM
Quote:
Originally Posted by daveT
Technically, you can't have FP by reducing the matrix or rotating it, as that is mutation. The closest you can do is something that looks like this:
Sure you can, you just return a copy in your rotate function instead of rotating in place
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 06:47 PM
Quote:
Originally Posted by gaming_mouse
my feeling is that clarity and simplicty are orders of magnitude more important than performance until performance specifically asserts itself as a pressing need.
If you think this is a general principle to follow...

Quote:
Originally Posted by gaming_mouse
as for the second point, it's a straw man. i mean, your argument is that there's going to be a problem with ramda's "pipe" or "reverse" implementation? that's just... no.
Don't forget that abstractions you use may have been created with the same principle in mind.

It's kind of like no free lunch thing. For you to worry about the essence of the problem or whatever, other people have to work harder to create abstractions that are very robust, which usually means they can't simply write code that focuses on the meat of the problem.

It's a little odd to say in your code, performance doesn't matter because you can fix it when it becomes a problem but that other people's code can be trusted to have the performance characteristics you need.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-22-2016 , 08:57 PM
Quote:
Originally Posted by candybar


Don't forget that abstractions you use may have been created with the same principle in mind.
yes, and they have been, by very smart people who have spent untold hours on the problem, starting back in the 1950s and even before.

Quote:
It's kind of like no free lunch thing. For you to worry about the essence of the problem or whatever, other people have to work harder to create abstractions that are very robust, which usually means they can't simply write code that focuses on the meat of the problem.
correct. i never said that nobody needs to worry about these things -- just that's it's only appropriate for low-level work. for many reasons having to do with history, language popularity, the way CS is taught, etc, normal programmers who absolutely shouldn't be thinking about this kind of thing but should instead be learning how to use high-level constructs well have been poisoned into a style of programming that is completely inappropriate for their work.

Quote:
It's a little odd to say in your code, performance doesn't matter because you can fix it when it becomes a problem but that other people's code can be trusted to have the performance characteristics you need.
there isn't anything the least bit odd about this. for the majority of business applications, it's just not an issue. also, this approach is so common it's entrenched in a miliion CS aphorisms: "premature optimization is the root of all evil", "Make It Work Make It Right Make It Fast," etc.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 12:27 AM
Quote:
Originally Posted by gaming_mouse
yes, and they have been, by very smart people who have spent untold hours on the problem, starting back in the 1950s and even before.
Concepts are not implementations.

Quote:
correct. i never said that nobody needs to worry about these things -- just that's it's only appropriate for low-level work.
All work becomes low-level when people build on top of your software. And all successful pieces of software tend to become something other people build on top of. Talented people don't want to work on the periphery forever. Untalented people tend not to make optimal use of advanced concepts and tend not to work on problems that are complex enough for these concepts to make a difference.

Quote:
normal programmers who absolutely shouldn't be thinking about this kind of thing but should instead be learning how to use high-level constructs well have been poisoned into a style of programming that is completely inappropriate for their work.
Normal programmers, in my experience, simply don't have the mathematical background to successfully write code where currying and point-free style are common. It adds significant cognitive overhead which is not really necessary given that most of the code they are writing is gluing together existing components and iterating as requirements evolve. Most programmers are best off adopting the conventions for the mainstream languages and frameworks because they are mostly solving an integration problem and seamless integration projects in the long run require compatibility, in conventions as well as in technologies. If you're not creating a platform, following the rules of the platform tends to be the path of least resistance.

Looking at this from another angle, size and complexity of the software matter. For small code bases, not much matters because there just isn't much complexity - most of the complexity is in other people's code you're using, which is minimized if you use mainstream technologies in a standard way. For large code bases, all kinds of factors become important - ecosystem, tooling, consistency across developers, readability, traceability, transparency, integration with other systems and these all favor mainstream technologies and limiting the level of abstraction to a manageable level. It doesn't matter some piece of functionality was implemented in 20 lines or 5 lines.

Also high-level design is completely divorced from low-level implementation at that level. You can write a stateful mess that is hard to understand in Haskell and you can write a software transactional memory system in C. The semantics of your system does not have to resemble the semantics of the language your system was written in. Any kind of real world system these days consists of multiple processes, multiple machines, multiple everything, across which language semantics can't be enforced. Runtime performance and control do matter - often it's precisely because you want to allow your users to have a high-level experience that you have to go further down in your stack.

Quote:
for the majority of business applications, it's just not an issue.
For the vast majority of business applications, whatever mainstream technology they are teaching in bootcamps works fine.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 01:05 AM
does it bother you at all that your argument, almost exactly, could have been made at any point in the history of computing, whether the "mainstream" was binary, fortran, or java 1.0?

it's just a total nonsense justification of the status quo and a straw man of my position.

there's no point in continuing the argument. i just fundamentally disagree with you.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 01:19 AM
Quote:
Originally Posted by RustyBrooks
Sure you can, you just return a copy in your rotate function instead of rotating in place
Yes you can, but I'd argue you shouldn't. This creates a unintended global state, which means you may as well be doing it in OO instead of FP. Doing stuff like this is okay for small toy programs, but falls apart and becomes extremely complex to handle once you get to a significant LOC, which is around 300 LOC, so not like huge. I'd rather just not mutate the matrix at all, since this is better FP practice, IMO.

I am suggesting that you can mutate the indices but that is only because it is self-calling and because that mutation is localized to a single function. In general, all functions in an FP programs should be immutable accept for a handful of functions that run all the looping and state management.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 01:55 AM
Quote:
Originally Posted by gaming_mouse
does it bother you at all that your argument, almost exactly, could have been made at any point in the history of computing, whether the "mainstream" was binary, fortran, or java 1.0?
And if you were a regular business developer, doing whatever was mainstream was the correct answer! And advances are made by people worrying about things you're saying people shouldn't worry about. Advances are not made by business developers idly worrying about how to utilize latest fads to write the fewest lines of code and not care at all about runtime performance. There's an attribution flaw here where you're crediting consumers for the improvements made by the producers. If you're going to create new abstractions that change the world for the better, you need to start caring about what you produce, not what you consume. If you're using something new, it should be because it's enabling you to do something you couldn't do before, not because it allows you to write the same thing you always could write, but slightly shorter or prettier or whatever.

Quote:
Originally Posted by gaming_mouse
correct. i never said that nobody needs to worry about these things -- just that's it's only appropriate for low-level work. for many reasons having to do with history, language popularity, the way CS is taught, etc, normal programmers who absolutely shouldn't be thinking about this kind of thing but should instead be learning how to use high-level constructs well have been poisoned into a style of programming that is completely inappropriate for their work.
And I'll say whatever technology or style of programming that isn't popular for platform-level programming will never be popular. C would not have become historically significant if it was for applications-only - it was popular because it was used to write an OS. Java would not be where it is if Java programmers simply consumed platforms written in other languages - it got to where it is because it became a massive platform on its own. JavaScript wasn't that popular when it was used as glue for technologies implemented in the browser - it became popular when it became a platform with its own libraries and frameworks.

And speaking as someone who has a genuine interest in programming languages and models of computation, I've never seen any evidence that the kinds of differences matter in the large. GC matters for productivity. Lambda does, but to a much lesser degree. Static types matter for large code bases. Type inference matters, but progressively less at larger scale. Sane ways to do concurrency matter (threads and locks are too low-level for most people). Dynamic dispatch matters a little. Once you get to this kind of baseline, I just don't see much evidence of improved productivity. I've written functional programming libraries for Perl to do the kinds of thing ramda does way back when this wasn't popular. Looking back, I don't see any productivity gains that came from it.

Again, if you have something technically challenging to build, then you need to do what's right from a technical perspective. Requirements are going to drive technology choices. The problem right now here is that you're trying to justify a technically inferior or neutral solution as being better for social reasons in situations that are not particularly technically challenging enough to warrant deviation from the mainstream.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 04:04 AM
GM vs CB could bring the internet down. Stock up on canned goods everyone.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 10:55 AM
Quote:
Originally Posted by suzzer99
GM vs CB could bring the internet down. Stock up on canned goods everyone.


i should make clear to anyone who doesn't know my history with him that candybar is one of my favorite posters here. i just happen to completely disagree with him on this point.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 01:36 PM
Quote:
Originally Posted by gaming_mouse


i should make clear to anyone who doesn't know my history with him that candybar is one of my favorite posters here. i just happen to completely disagree with him on this point.
FWIW very interesting, informative, and high quality discussion.

You posted:

Quote:
Originally Posted by gaming_mouse
does it bother you at all that your argument, almost exactly, could have been made at any point in the history of computing, whether the "mainstream" was binary, fortran, or java 1.0?

it's just a total nonsense justification of the status quo and a straw man of my position.

there's no point in continuing the argument. i just fundamentally disagree with you.
I agree with this point.

However, again FWIW, it should be noted also that processor technology has advanced greatly as well. In my view this has been a tremendous assistance in developing more and better high level languages. Better in the sense that complexity becomes easier to manage which I believe is one of your main points. Now that processor speeds (at least with microprocessors) have maxed out for the time being (due to physical limitations with transistor density and such) we are probably going to see more emphasis on concurrency in solutions.

A while ago I made a post about processors scaling up and the main point was that software will continue to be utilized to handle increasing amounts of complexity and managing that complexity requires more sophisticated languages.

A long winded way of stating I think you both have valid points.

Last edited by adios; 09-23-2016 at 01:53 PM.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote
09-23-2016 , 10:35 PM
Quote:
Originally Posted by gaming_mouse


i should make clear to anyone who doesn't know my history with him that candybar is one of my favorite posters here. i just happen to completely disagree with him on this point.
I'd definitely say the same about you. I'll add that part of the reason why I'm writing so much on this topic and may seem overly argumentative is that my personal preferences more or less line up exactly with yours. But I feel that the evidence simply doesn't support that my preferences are any more conducive to being productive than others' and feel that clinging to them at times has had a negative impact on my career. I've sort of had to convince myself that wait, I don't actually have any evidence that this is the better way.

In particular, I think the idea that very easily follows from this disposition - that other people, the great masses, are doing things the wrong way - is very counterproductive from the perspective of becoming a more effective engineer.
Interview  Test Questions Problems, Solutions, Links, Discussion Quote

      
m