madbernard: a long angled pier (Default)
2015-08-13 02:05 pm

Finding bugs in other people's code is surprisingly gratifying

Just did a Coderbyte challenge that was, "given an array of numbers that could be positive or negative but which will not include 0, return 'Arithmetic' for arrays where there's the same distance between all the numbers, 'Geometric' for arrays where there's the same multiple between all the numbers, and -1 for everything else." My answer isn't the best it could possibly be (I feel that I'm using Math.abs poorly, and I should have taken a moment more to make the reduce part bring back the biggest number in the difference array... averages can be deceiving), but looking at answers from unnamed other people, several of them don't even work. This one only compares the gap in numbers of the first two and last two in the array:
function ArithGeo(arr) { 
  var isArithmetic=(arr[1]-arr[0]==arr[arr.length-1]-arr[arr.length-2]);
  var isGeometric=(arr[1]/arr[0]==arr[arr.length-1]/arr[arr.length-2]);
  // code goes here  
  if(!isArithmetic&&!isGeometric){//is not special
    return -1;
  }else{
    return (isArithmetic)?'Arithmetic':'Geometric';
  }
}
It can be defeated with [1,2,45,99,100]. I saw this same pattern three times in like six answers I looked over. Interesting to catch stuff that the tests don't. When I started this post I was feeling a cheerful about not being at the bottom of the heap, but now I'm a bit sad. Anyway, here's my answer. Tell me about better ways of checking that every number in an array is the same... I could have done another for loop, "if difference array [i] !== difference array [0] return false"...
function ArithGeo(arr) { 
  var geo = [];
  var arith = [];
  for (var i = 0; i < arr.length - 1; i++) {
    geo.push(Math.abs(arr[i + 1] / arr[i]));
    arith.push(Math.abs(arr[i + 1] - arr[i]));
  }
  var sumGeo = geo.reduce(function(prev, curr){
    return prev + curr;
  });
  var sumArith = arith.reduce(function(prev, curr){
    return prev + curr;
  });
  if (sumGeo / geo.length === geo[0]) {return 'Geometric';}
  if (sumArith / arith.length === arith[0]) {return 'Arithmetic';}
  return -1; 
}
madbernard: a long angled pier (Default)
2015-08-12 04:52 pm

More Regex Complications!

Here's one I thought would be simple, which wasn't. The problem is, "return a count of all the vowels (not y) in a string." I thought I'd use regex.exec to capture an array of vowels and find the length of the array... But it only ever returned length 2. I see in the Mozilla Developer Network info page that RexExp.length is 2, but I don't know why I'm getting that here. Can someone troubleshoot?
function VowelCount(str) { 
  var re = /([aeiou])/ig;
  var arr = re.exec(str);
  console.log(arr);
  return arr.length; 
}

console.log(VowelCount('moooo'));
So I pivoted to for loops and came up with this,
function VowelCount(str) { 
  var re = /[aeiou]/i;
  var count = 0;
  for (var i = 0; i < str.length; i++) {
    if (re.test(str.charAt(i))) {
      count += 1;
      console.log(i);
  }
  return count; 
}
This also took some troubleshooting, since the count was wrong when I was using the 'g' flag in the regex. I'm also not sure why that was. Other people I looked at also had mangled looking answers, though of course Matt Larsh has something good,
function VowelCount(str) { 
  var vowels = str.match(/[aeiou]/g);
  return vowels.length;
}
Looks like I need to bone up on str.match.
madbernard: a long angled pier (Default)
2015-08-12 04:09 pm

RegEx for Some, Tiny American Flags for Others!

Last evening I had a moment and tried the Coderbyte challenge "when given a string of single letters, plusses, and equals signs, return true only if every letter has a plus on both sides". I came up with a four part if statement reliant on regexes.
function SimpleSymbols(str) {
  if (/(\+\w\+)+/g.test(str) && !/^\w/g.test(str) && !/=\w/g.test(str) && !/\w(?!\+)/g.test(str)) 
  {return true;}
  else {return false;}
}
In English, that's if there is a plus on either side of a letter, and if there is no letter at the start of the string, and if there is no letter with an equals sign immediately in front of it, and if there is no letter that is not followed by a plus sign... Then true.

Ben, who does JS for a living, gave me the learning that if there's more than one regex, it's probably not ideal... "There's so many edge cases". Makes sense. So, later, the Coderbyte challenge appears, "when given a string of lowercase letters, if there is an a followed by a b three spots later, return true". And I'm like, "I'll use a for loop, like we were talking about last night!"Read more... )
madbernard: a long angled pier (Default)
2015-08-11 05:10 pm

Coderbyte easy 5 and 6

Challenge 5 was, given a number between 1 and 1000, add up all the numbers inclusive in that set. Obviously I could repurpose Matt Larsh's recursive function to do this, so I did so, and it worked first try. Woo! Though, no one else seems to be doing +=. I wonder if this would be super wrong if I wasn't recursing and thus seeing it only once each function call? Or do they just like num + SimpleAdding(stuff)?
function SimpleAdding(num) {
  if (num === 1) {
    return 1;  
  }
  else {
    return num += SimpleAdding(num - 1);
  }      
}
Challenge 6 was one I hadn't yet solved in Free Code Camp: Capitalize every word in a string. I abandoned a couple different paths while trying for speed, and eventually came up with this answer that seems cludgy:
function LetterCapitalize(str) { 
  var foo = str.split('');
  var bar = [];
  bar.push(foo[0].toUpperCase());
  for(var i = 1; i < foo.length; i++) {
    if (foo[i - 1] === ' ') {
      bar.push(foo[i].toUpperCase());
    }
    else {
      bar.push(foo[i]);
    }    
  }
  console.log(bar.join(''));
  return bar.join('');
}
LetterCapitalize('to see how to enter arguments in JavaScript');
I tried replacing the space in the if statement with /\s/ and that didn't work, nor did /\s/g; I'm not sure why not.

One of my abandoned paths was to do a str.replace(regex, function) but I wasn't getting the function to work... So I was super curious to see what Matt Larsh did, and sure enough he did something cool:
function LetterCapitalize(str) { 
  return str.replace(/\b[a-z]/g,function(c){return c.toUpperCase()});
}
That "\b" was something I thought should exist, but didn't find: the signal for "match a word boundary". I just tried /\b\w/g and that works, too; I suppose his way is better, though, since it limits the capitalization to only things that we absolutely know need capitalizing. Unless if \w includes accented letters and other slightly less usual things? My RegEx skillz are not yet l33t and m4d.
madbernard: a long angled pier (Default)
2015-08-11 01:29 pm

Easy Coderbyte challenges 3 & 4

Remembering these from last week: Challenge 3 was another I'd done before, "find the longest word in the sentence", and I got a few more refinements in my answer: I used a regular expression to create the first array; and (having discussed it with Ben) I used an empty string as the initializing value. The previous stab at this Reduce, where I was trying to initialize with 0, was comparing apples and oranges in the form of numbers and strings.
function LongestWord(sen) { 
  var arr = sen.split(/(\w+)/g);
  var foo = arr.reduce(function(prev, curr){
    if(prev.length < curr.length){
      return curr;
    } else {return prev;}
  }, '');
  return foo; 
}
Looking over other answers, I think reduce is by far the most elegant path. Wooo! Arrays FTW!

Challenge 4 was ...a journey. Read more... )
madbernard: a long angled pier (Default)
2015-08-05 01:49 pm

CoderByte Factorial, me vs others & vs recursion

Factorial happened last week, also; the CoderByte challenge was, we'll test on numbers between 1 and 18, give us that number multiplied by every non-0 integer less than it. Ben-the-housemate suggested that this could be done recursively, so I tried that first, but didn't hack it; so, given the ticking clock, I aborted to the exact same decreasing for-loop plan I'd used last week. Looking through other answers was gratifying... I was among the most elegant! I found the recursive method from user mattlarsh, in a tiny tidy package:
function FirstFactorial(num) { 
  return num<=1?1:num*(FirstFactorial(num-1)); 
}
He's using the ternary operator there, the shortest possible way to say if/then. IF: the num is less than or equal to 1, DO THIS: return 1, AND IF IT'S NOT: multiply the num by FirstFactorial num-1. So once he has a stack of not-quite-resolved functions and the num gets to 1, it returns 1 and then the rest of the stack has all the numbers it needs to work with and can resolve the final return.

My first pass on recursion was the below, and I got stack overflow (infinite program), which I can see now is because the num kept getting bigger but the recursion would only end when the num got to 0.
function FirstFactorial(num) { 
if (num > 0) {
num *= (num - 1);
FirstFactorial(num);
}
  return num; 
}

FirstFactorial(5);   
madbernard: a long angled pier (Default)
2015-08-04 05:19 pm

Beginning CoderByte easy tests

I looked at the Hack Reactor suggestions for what one should be able to do before applying, and headed over to http://www.coderbyte.com to try their easy track. They score submissions based not only on correctness, but on time, which is not at all my bag. I think when I saw that a year ago I just turned away, even though a friend suggested doing it on my own time and then pasting the answer in... I might do that in the future.

Their first question was the exact same as I saw last week; reverse a string. I came up with this, which, amusingly, is not what I did last week. It uses the join method of arrays that I was searching for last week, so I'm pleased that knowledge is in me...
function FirstReverse(str) { 
  var hold = [];
  for(var i = str.length - 1; i >= 0 ; i--){
    hold.push(str[i]);
  }
  var foo = hold.join("");
  return foo; 
}

FirstReverse("stuff");           
Also, heeey, check out the respect of spacing in that code block. I thought there were HTML tags about code, and found <code> and thought that was it... Ben the housemate says code isn't really a HTML tag and turned me on to <pre>. Thanks!

Anyway, a good thing about CoderByte: they let you see what other people did, after, answering the socrating question of my friend Catherine about whether I looked at other people's solutions. There's a solution like mine above, but relying on methods of strings and arrays that I wasn't aware of; and that solution lets one do everything in a single line!
function FirstReverse(str) { 
  return str.split('').reverse().join('');
}
Way more elegant.
madbernard: a long angled pier (Default)
2015-07-30 03:11 pm

Don't quite understand Reduce

The next Free Code Camp exercise is to find the length of the longest word in a string (and all of their test strings are free of anything but letters and single spaces). Good points: I had no trouble getting the shape of the solution, and split totally worked great. Actually doing the proper syntax for Reduce required a lot of searching, though, and eventually I basically copied a bit from this webpage about getting comfy with arrays. I should work through that website sometime... Most of the failed reduce trials I don't have copies of, but one that I don't understand is that when I had a 0 in the place I thought was for initial value, right after the anonymous function and before the console.log error-catching readout, here: }, 0);
console.log(foo.length);
what I got out of the function was only 0. Baffling. Below is code that works. :)

function findLongestWord(str) {
var words = str.split(' ');
var foo = words.reduce(function(prevWord, thisWord){
if (thisWord.length > prevWord.length) {
return thisWord;
}
else {
return prevWord;
}
});
console.log(foo.length);
return foo.length;
}

findLongestWord('The quick brown fox jumped over the lazy dog');
madbernard: a long angled pier (Default)
2015-07-29 05:20 pm

Free Code Camp Bonfire 4 and 5

So, 4 was trivial, which was great: make a function that factorializes numbers. Like, 5! is 1 * 2 * 3 * 4 * 5 = 120.

function factorialize(num) {
for (var i = (num - 1); i > 0; i--) {
num *= i;
}
return num;
}

factorialize(5);

But 5... I feel like I shouldn't have to make my own function that takes an array and jams it all into a single string without commas separating the bits. But the concat stuff I was looking at in the Mozilla Developer Network wasn't working that way (even though their example shows it should. So baffled).

And I feel like there must be some way to not declare like 7 variables... But I couldn't figure out how to chain these methods/functions. Anyway: here it is, a function that checks if a statement is a palindrome (ignoring all the non-letter things! The RegEx stuff was honestly fun learning).

function reverseString(str) {
var reverseStr = '';
for (var i = str.length - 1; i > -1; i--){
reverseStr += str[i];
}
return reverseStr;
}

function arrToRevStr(arr) {
var str = '';
for (var i = arr.length - 1; i > -1; i--){
str += arr[i];
}
return str;
}

function palindrome(str) {
var cleanStrArray = /(\w)/g.exec(str);
var cleanStr = arrToRevStr(cleanStrArray);
var cleanStrLow = cleanStr.toLowerCase();

var reverseStr = reverseString(str);
var cleanReverseStrArray = /(\w)/g.exec(reverseStr);
var cleanReverseStr = arrToRevStr(cleanReverseStrArray);
var cleanReverseStrLow = cleanReverseStr.toLowerCase();

if (cleanStrLow == cleanReverseStrLow) {return true;}
else {return false;}
}

palindrome("eye");
madbernard: a long angled pier (Default)
2015-07-29 03:35 pm

Reversed a string woo!

I feel like I've reversed a string before... I vaguely remember something about halving the length and swapping things around the middle. But this time, when Free Code Camp asked for it as their very first JavaScript coding exercise, I just looped through the entire thing. Woooo!

function reverseString(str) {
var reverseStr = '';
for (var i = str.length - 1; i > -1; i--){
reverseStr += str[i];
console.log(reverseStr);
}
return reverseStr;
}

reverseString('hello');

At first I had just defined the reverseString variable as "var reverseStr;", and the readout I was getting from that console.log in the loop was "NaNo" "NaNol" etc. Second debugging step, when I made the start point of the loop i = str.length - 1 instead of i = str.length, I got "undefinedo" "undefinedol" "undefinedoll" etc. So in the first case it was trying to add the nothing in "hello"[5] to NaN, since why, the sensible programming language thinks, would I be trying to use an addition operator, +, on anything but a number? I'm not sure why trying to add "o" worked; I suppose JavaScript decided that the o it was getting meant that it should be adding to a string or object or some non-number thing, but that string or object or whatever wasn't defined. It's nice that when it failed at adding it relapsed to concatenating.

...I suspect this is a terrible implementation of reversing a string. Any takers?

The Free Code Camp at this point suggests I should be pairing, and a nice guy in the chat room linked me up with a copy of Screenhero (they've joined Slack and are not taking new signups unless someone already inside invites you in), which they suggest is good for being able to remotely cowork and see everything on another screen... Another guy in the chat suggested coderpad.io or another .io solution instead, as less dangerous and better functioning. What do people think, re: screen sharing programs?
madbernard: a long angled pier (Default)
2015-05-14 08:11 pm

Eloquent Javascript problem 6.3

I've been sick this past week, which didn't stop me vs. 6.1 and 6.2, but when I hit 6.3 I couldn't even figure out what he was asking. It's like he's saying, design a protuberance on the center of your face, then use that protuberance to detect a scent. ...Does he mean find your nose, or does he mean build yourself a new nose? That second one seems a bit unnecessary. Or to be less metaphorical, what am I missing? Iterating over arrays and objects seems like a major portion of what we've been doing so far. The emphasis on interface has got to be meaningful, but the gap between that text analysis and understanding the reason behind the question is fairly daunting.

I'm posting now because I at least figured out something, though I'm fairly sure I'm deep in the weeds heading in a direction that would baffle and amaze all who came after me.

I wondered what methods came baked in to objects, like forEach does on arrays. So I googled, and found this StackExchange bit, http://stackoverflow.com/questions/5842654/javascript-get-objects-methods

which lead me to screw around in JSBin seeing what came included in the Object package,
console.log(Object.getOwnPropertyNames(Object)); and
console.log(Object.getOwnPropertyNames(Object.prototype));

And then there were all sorts of interesting things to look up:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object

Moving forward with Object.keys, I tried this out as a start of an attack on 6.3, adding the console.log stuff in the midst of the program when it initially didn't return what I expected. Thanks to my housemate Ben for that general technique! What I was trying to do here is to get it to pull out a value from a Seq object at any given point:

var Seq = function(object) {
this.object = object;
};
Seq.prototype.valueAtI = function(i) {
var keyArray = [];
keyArray.push(Object.keys(Seq));
console.log(keyArray);
for (var j = 0; j < (i || keyArray.length); j++) {
if (j == i)
return keyArray[i];
else
return "There are fewer things in the sequence than that";
}
};

var foo = new Seq;
foo.bar = "baz";
foo.bear = "bearz";
foo.pear = "pearz";

console.log(foo.valueAtI(1));

The results were [[]] / There are fewer things in the sequence than that . I'd varied the value of i, even down to 0 ("undefined"), but it was the second set of brackets that tipped me off. Less broken code below:

Seq.prototype.valueAtI = function(i) {
var keyArray = Object.keys(this);
console.log(keyArray);
for (var j = 0; j < (i || keyArray.length); j++) {
if (j == i)
return keyArray[i];
else
return "There are fewer things in the sequence than that";
}
};

This actually results in an array of the keys of the object. It doesn't do what I meant it to do, and I think I can see why now that I'm writing, but it's pretty late and I'm taking the tiny win.
madbernard: a long angled pier (Default)
2015-05-07 12:02 pm

Eloquent Javascript problem 5.4, "Every and then some"

There I was on Eloquent Javascript's problem 5.4, http://eloquentjavascript.net/05_higher_order.html#h_jr7hZiuR7+

The for loop seemed simple, but what I came up with wasn't processing "isNaN" as a function.

var every = function (array, compare) {
for (var i = 0; i < array.length; i++) {
if (array.i !== compare)
return false;
else return true;
}
};

console.log(every([NaN, NaN, NaN], isNaN));
// → should be true, but was showing as false
console.log(every([NaN, NaN, 4], isNaN));
// → false


Putting the "compare" in the if condition in () parentheses (because I had a memory that some form of parentheses would make javascript try to find the value of a thing... Thinking about this, that was probably a memory from getting values of keys, done with [], which in this case I believe would flag "compare" as an array) didn't fix it. Trying for != to allow for type conversion didn't fix it.

I looked at the hints, and they didn't talk about making functions do their thing; they talked about setting up the loop like "forEach". I took an abortive stab at redoing the loop to use forEach... This didn't run, and the linter in JSBin was sad about my use of break. (I'm still not sure what's up with break.)

function every (array) {
array.forEach(function(compare) {
if (array !== compare) {
break;
}
else return true;
});
return false;
}


I tabbed over to the annotated book: https://docs.google.com/document/d/1aa2-HtUglQrAps31s4LdTPVsiFb1BxhyjZolxeezzcI/edit?_escaped_fragment_=#!
Predicate functions were never defined in the book so I’ll quickly explain them here.

A predicate function is a function that returns true or false based on some condition. In this problem, we’re using isNaN(testValue), which returns true if testValue is NaN (remember this means not a number), and false otherwise.

Huh. At first that seemed a bit unfair, a new unexplained type of function. But then, a closer reading would have indicated that the compare thing had to be a function; and I'd even previously went back to the appearance of isNaN in Eloquent Javascript and managed to whizz past the part where it was summoned into action like so, isNan("some thing").

The working answer,
var every = function (array, compare) {
for (var i = 0; i < array.length; i++) {
if (!compare(array[i]))
return false;
}
return true;
};

And "some" is trivial from there.