Craig Rodrigues!

Learning to Code: Week 12 - CS50x Coding Contest!

7/29/16

  • Traits of a Proficient Programmer (thanks Shawn!)
    • If explaining a codebase to a beginner, a proficient developer may decide to stick to the basics of what the code is actually doing rather than throwing out named patterns and telling a novice "Go read the Gang of Four before asking me any questions."
    • Dig into primary sources rather than just reading summaries. It takes more work, but helps you figure out both the basis and the boundaries of a technique, and also gives you an opportunity to generate new ideas of your own that are inspired by core principles.
    • Ask others to explain why they do things, but don't just accept dogmatic reasoning. Demand examples and inquire about context, so that you can try to imagine what it is like to be in their shoes. Doing this is tremendously valuable because it allows you to see the strengths and weaknesses of ideas in their natural habitats.

image11

  • http://tinyletter.com/programming-beyond-practices/letters/on-interviewing-candidates-for-programming-jobs
    • A meaningful portfolio of work, whether it's professional or personal.
    • Ability to talk through and ask good questions about realistic problems in whatever business domain your company is in.
    • Sufficient communication skills and technical competence to explain some code they've written, at both the high level and at the detailed level.
    • A mindset that emphasizes customer service and a focus on business outcomes rather than raw technical interests.

7/30/16

Couldn’t find a team for the CS50 coding challenge so I’m going solo.

  • First problem is called “Punctuation.

Write a program that, given a line of text, T, via standard input, prints it to standard output with the following modifications:

After every period (.) and comma (,), a space must be added.

The first letter after every period must be capitalized.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "cs50.h"

int main(void)
{
    string sentence = GetString();
    int period_flag = 0;

    //loop through the sentence given
    for (int i = 0; i < strlen(sentence); i++)
    {
        if (period_flag == 1) //marker to see if we have run across a period or not
        {
            printf("%c", toupper(sentence[i])); //if we have then next character must be uppercase
            period_flag = 0; //reset flag for next period
        }
        else if (sentence[i] == ',')
            printf(", ");

        else if (sentence[i] == '.')
        {
            period_flag = 1;
            printf(". ");
        }
        else
            printf("%c", sentence[i]);   
    }
}

  • Second problem is called “Money, Money, Money.”

Write a program that takes in three values via standard input: a starting bank account balance, B, in dollars; an annual interest rate, R; and a number of years, N. The program should print out the value of the resulting bank account balance after B has received interest at rate R calculated annually for N years, rounded to the nearest cent.

For example, if B is 280.00, R is 0.01 (representing a 1% interest rate), and N is 3, then your program should print out 288.48, which represents the final balance after an initial balance of $280 receives 1% interest calculated once per year for three years.

Expect B and R to be floating-point values and N an integer.

Input Format

Your program will take three lines of input:

The first line will be a floating-point value, B, representing the starting bank account balance.

The second line will be a floating point value, R, representing an interest rate in decimal form.

The third line will be an integer, N, representing the number of years over which that interest should be calculated.

Constraints

B >= 0

R >= 0

N >= 0

There will be no percentage signs (%) or dollar signs ($), in the input, and you should not include either symbol in your output.

Output Format

A number representing dollars as a floating-point value, rounded to the nearest cent.

Sample Input

82

0.02

3

Sample Output

87.02

 

    • This one took a lot longer than it should have. I ran into stupid errors more than anything else. Also I used the incorrect formula for yearly compounded interest in the beginning. Damn you google.
    • Formula used: http://www.thecalculatorsite.com/articles/finance/compound-interest-formula.php
    • I round the value at the very end and then print to two decimal places, but my program fails one test case, but I don’t see how. I will move on since I can’t beat my head against an unknown wall.
    • If I try to round any earlier than the end I lose cents in precision and the interest rate doesn’t come out right at all.
    • My solution
#include <stdio.h>
#include <math.h>

#include "cs50.h"

int main(void)
{    
    double B = GetFloat(); // balance
    double R = GetFloat(); // interest rate
    double N = GetInt(); // years

    if (B < 0 || R < 0 || N < 0)
        return 0;

    double X = 1 + R;
    double Y = pow(X, N);

    double finalBalance = Y * B;
    finalBalance = roundf(finalBalance * 100) / 100;
    printf("%.2f", finalBalance);
}

 

  • Third problem is called “One More Year.

Write a program that, given a year, Y, as an integer via standard input, prints via standard output Leap Year if Y is a leap year, and Not Leap Year if Y is not a leap year.

Recall that:

A year is a leap year if it is a multiple of four (2004, 2008, and 2012 are all leap years). The exception to this rule is that a year which is a multiple of 100 and also not a multiple of 400 is not a leap year. For example, 1800 and 1900 are not leap years, but 2000 is a leap year (because it is a multiple of 400).

  • Very simple problem, but it requires the right kind of logic tree to get it right. I had it a little backwards at first. Didn’t take too long to get it all right.
  • Solution here
#include <stdio.h>
#include <math.h>

#include "cs50.h"

int main(void)
{
    int year = GetInt();

    if (year > 9999 || year < 0)
        return 0;

    if (year % 4 == 0)
    {
        if (year % 100 == 0 && year % 400 != 0)
        {
            printf("Not Leap Year");
            return 1;
        }
        printf("Leap Year");
        return 1;
    }
    else
        printf("Not Leap Year");

    return 1;
}

 

  • Skipped next problem since it only has a 29% completion rate. I’ll come back to it.
  • Next problem is called “Name Your Cat”

Between the words cat and kitten, there are seven unique characters (a, c, e, i, k, n, and t), because only those characters appear in the two words.

Given a string (i.e., a cat's name), reverse all instances of those characters, while leaving the other 19 letters in the alphabet as they are. Each of those 19 characters, if they appear in the name, must remain at the same index.

If there is only one character to reverse, leave it in the same location.

Input Format

You will take in 2 lines of input. The first will be N, the number of characters in the string. The second line of input will be the string S to be manipulated.

Constraints

N > 0

S will only contain lowercase letters.

Output Format

Your program should print the cat-reversed version of S to standard output.

Sample Input

12
davidmeowlan

Sample Output

dnvadmeowlia
  • This one wasn’t so bad except I got a little confused on how to structure my ending condition. After I ate lunch it was easy to spot and finish solving.
  • Only thing I don’t know how to do is shorten the giant list of if conditions.
  • My solution here
#include <stdio.h>
#include <string.h>

#include "cs50.h"

int main(void)
{
    int n = GetInt();
    string s = GetString();
    int i = 0;
    int j = 1;

    while (i < (n-j))
    {
        if (s[i] == 'a' || s[i] == 'c' || s[i] == 'e' || s[i] == 'i' || s[i] == 'k' || s[i] == 'n' || s[i] == 't')
        {
            if (s[n-j] == 'a' || s[n-j] == 'c' || s[n-j] == 'e' || s[n-j] == 'i' || s[n-j] == 'k' || s[n-j] == 'n' || s[n-j] == 't')
            {
                //swap
                char temp = s[i];
                s[i] = s[n-j];
                s[n-j] = temp;
                i++;
                j++;
            }
            else
            {
                //incrememnt j if we don't swap to find next viable char
                j++;
            }
        }  
    else
        i++;
    }
    printf("%s", s);
}

 

  • Fourth problem is simply called “X”.

Write a program that, given an odd integer, N, in [3, 23], draws a box (out of * characters) of height N and width Nwith an X in the middle. That is, the diagonals of the box should be drawn with * characters.

For example, 5 should give you:

*****  
** **  
* * *  
** **  
*****

And an input of 7 should give you:

*******
**   **  
* * * *
*  *  *
* * * *
**   **
*******

 

Input Format

An integer N that may be odd or even, and may or may not be in [3, 23].

Constraints

N will be an integer.

Output Format

A box with diagonals, drawn from * characters, provided N is odd and in [3, 23]. If N is even or is not in [3, 23], your program should not print anything.

Sample Input

5

Sample Output

*****  
** **  
* * *  
** **  
*****

 

  • I broke this problem down into parts when I’m sure it’s possible to do it with just two FOR loops. That seemed a little complex so I simplified it down to three parts
    • One, make the border of *’s
    • Two, make the X
    • Print the completed 2D array
  • The hardest part was getting the two for loops to get the X to work correctly. I had part 1 and 2 done quickly.
  • My solution is here
#include <stdio.h>

#include "cs50.h"

int main(void)
{
    int n = GetInt();

    if (n % 2 == 0)
        return 0;
    if (n < 3 || n > 23)
        return 0;

    int board[n][n];

    // counters
    int x = 1;
    int y = n-2;

    // loop through 2D array and put border around it
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (i == 0)
                board[i][j] = '*';
            else if (j == 0)
                board[i][j] = '*';
            else if (j == (n-1))
                board[i][j] = '*';
            else if (i == (n-1))
                board[i][j] = '*';
            else
                board[i][j] = ' ';
        }
    }

    // loop through at put the X down
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (x > 0 && x < n-1)
            {
                if (y > 0 && y <= n-2)
                {
                    board[x][x] = '*';
                    board[x][y] = '*';
                    x++;
                    y--;
                }
            }
        }
    }

    // print the final board
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            printf("%c", board[i][j]);
        }
        printf("\n");
    }
}

 

7/31/16

  • Didn’t get much time to work on my CS50 challenge, but did work on the problem called “Word Reverse.”

Write a program that, given a string, S, made up of ASCII characters, reverses each 'word' within S individually while leaving the general word order of S intact and prints the result to standard output.

A 'word' here is defined as any contiguous set of letter and number characters, uppercase or lowercase. Words are separated by any ASCII characters that are not letters or numbers.

For example, if a user inputs:

Hello world!, your program should print olleH dlrow!

Go ha.ng a salami, your program should print oG ah.gn a imalas

Wow, aren't you enjoying this 1337 contest?, your program should print woW, nera't uoy gniyojne siht 7331 tsetnoc?

  • I ran into a few issues with this one I put in the comments of my solution gist, but the reverseString function I had already created made the logic pretty trivial. I just need to look for a space or punctuation and switch any string before that (put into a temp array).
  • Once that is done clear the temp array and continue to the next space/punctuation and do it again or until I am at the end of the whole string.
  • Solution here.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "cs50.h"

char* reverseString(char* s);

int main(void) {

    char *str = malloc(sizeof(char *) * 200);
    str = GetString(); //get input from user

    char *temp = malloc(sizeof(char *) * 200);
    int j = 0;

    if (str == NULL)
        return 1;

    // loop through string copying to a temp string until a special character or space is found.
    for (int i = 0; i < strlen(str); i++)
    {
        if (isalnum(str[i]))
        {
            temp[j] = str[i];
            j++;
            if (i == strlen(str)-1) //this is a check to see if this is the last character
            {
                reverseString(temp); // reverse temp string and print
                printf("%s", temp);
                j = 0; // reset back to beginning of temp array once we find a special character
                memset(&temp[0], 0, sizeof(temp)); // clear temp array
            }
        }
        else if (!isalnum(str[i]))
        {
            reverseString(temp); // reverse temp string and print
            printf("%s", temp);
            printf("%c", str[i]); // print space/special character
            j = 0; // reset back to beginning of temp array once we find a special character
            memset(&temp[0], 0, sizeof(temp)); // clear temp array
        }
    }

    free(str); //free memory
    return 0;
}

char* reverseString(char* s) {

    int length = 0, i = 0;
    length = strlen(s);
    char temp[1];

    for(i = 0; i < length/2; i++)
    {
        *temp = s[i];
        s[i] = s[length-i-1];
        s[length-i-1] = *temp;
    }
    return s;
}

Problems I encountered:

  1. I needed a way to clear my temp array after each swap. Looked that up and got an answer to just clear the memory which worked well.
  2. Initially used scanf instead of GetString. Scanf only goes up the first space character which is a problem.
  3. If my string didn't end in a special character it wouldn't work, so I needed to add a check to see if we were on the last index of the string and then do the reversing and printing if that was the case.
  4. I didn't put in a check for a NULL string.
  5. I didn't realize that it wasn't just alpha characters that needed to be switched, but alphanumeric. So instead of isalpha you have to use isalnum.
  6. I used my initial reverseString function I created for leetcode problem.
  • Unfortunately I submitted this solution about 5 minutes after the competition ended so it didn’t count.
  • I printed out the rest of the problems as PDFs so I can work on them later, but it looks like I can do them whenever I want and check them on Hackerrank it just won’t count for anything.
  • The Maze Runner problem looks incredibly hard!

Write a program that reads from standard input a grid-based standard maze (no loops) represented in ASCII characters, and prints, on standard output, the sequence of positions comprising the shortest path from the start to the exit that passes through no walls of the maze. The start will be the position at the top left of the grid (represented by [0, 0]), and the exit will be the position at the bottom right.

Each successive position in the shortest path must be obtainable from the previous position by incrementing or decrementing one coordinate.

Input Format

The maze will be composed of the ASCII characters +, -, |, space (), and newline (\n).

- and | characters represent walls.

A space either represents the center of a grid square, or, if between two + characters, a passageway (the absence of a wall).

The maze does not need to be square, so its size will be N x M.

Constraints

N >= 2

M >= 2

The maze entrance (starting position) will always be the top left corner, [0, 0].

The maze exit will always be the bottom right, [N - 1, M - 1].

Every position in the maze will be reachable from the start. There will only be one correct shortest path. There may be wrong directions.

Output Format

A set of positions, formatted

[a, b]\n[c, d]\n..., where the letters stand for integers representing [row, col] of the positions comprising the path from the start to the exit. The first coordinate should always be [0, 0]. There should be a newline after each position, including the last. The last coordinate should always be [N - 1, M - 1].

Sample Input

+ +-+-+-+
| |   | |
+ + + + +
|   |   |
+-+-+ +-+
|     | |
+ +-+-+ +
|       |
+-+-+-+ +

Sample Output

[0, 0]
[1, 0] 
[1, 1] 
[0, 1] 
[0, 2] 
[1, 2] 
[2, 2] 
[2, 1] 
[2, 0]
[3, 0] 
[3, 1] 
[3, 2] 
[3, 3]

 

8/1/16

8/2/16

Given an array of  integers, can you find the sum of its elements?

Input Format

The first line contains an integer, , denoting the size of the array.

The second line contains  space-separated integers representing the array's elements.

Output Format

Print the sum of the array's elements as a single integer.

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

// https://www.hackerrank.com/challenges/simple-array-sum

int main(){
    int n; 
    scanf("%d",&n);
    int arr[n];
    int sum = 0;

    for(int arr_i = 0; arr_i < n; arr_i++){
       scanf("%d",&arr[arr_i]);
       sum += arr[arr_i];
    }

    printf("%i", sum);
    return 0;
}

 

  • I was helping a guy with his pset1 problem “greedy” on reddit. I then looked back at my code and cleaned it up a little bit. There were a few shorter ways of writing the program.
  • It is cool to look back and see a slightly better way of doing things.

8/3/16

  • First-Ever CS50x Coding Contest 2016 Postmortems
    • The above post is really cool since it shows the winners and some statistics
    • Also what is fucking sweet is there are videos showing how to solve all the problems! Now I get to see how they solved some of the more algorithmic problems that were way above my head (bus queue and maze runner).
    • Holy fuck looking at the first problem and they way they did it is blowing my mind. Their solution is way more simple than mine is by looking at individual characters rather than individual words as I was! I completely over-complicated my approach! https://youtu.be/QJNDhhBETSw

image23

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(){
    int alice_score = 0;
    int bob_score = 0;

    int a0; 
    int a1; 
    int a2; 
    scanf("%d %d %d",&a0,&a1,&a2);
    int b0; 
    int b1; 
    int b2; 
    scanf("%d %d %d",&b0,&b1,&b2);

    (a0 == b0) ? : ((a0 > b0) ? alice_score++ : bob_score++);
    (a1 == b1) ? : ((a1 > b1) ? alice_score++ : bob_score++);
    (a2 == b2) ? : ((a2 > b2) ? alice_score++ : bob_score++);

    printf("%i %i", alice_score, bob_score);
    return 0;
}

 

for(int i = 0, j = n-1; i < n; i++, j--){
       diagonal_sum1 += a[i][i];
       diagonal_sum2 += a[i][j];
}

 

8/4/16

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(void)
{
    int hours, minutes, seconds;
    char time[3];
    scanf("%d:%d:%d%s", &hours, &minutes, &seconds, time);

    if (hours < 12 && (strcmp("PM",time) == 0))
    {
        hours += 12;
    }
    if (hours == 12 && (strcmp("AM",time) == 0))
    {
        hours = 0;
    }

    printf("%02d:%02d:%02d", hours, minutes, seconds);
    return 0;
}

 

  • This morning I completed the final warmup problem on HackerRank because why not? Circular Array Notation: https://www.hackerrank.com/challenges/circular-array-rotation
    • I was actually surprised by this one because the code I wrote initially almost worked completely right away which hasn’t ever happened before. It means maybe I’m getting slightly better at figuring out the logic.
    • My loops had the incorrect constraints, but after fixing those the code worked.
    • I made a temp array to put in the modified shifted numbers, but that really isn’t necessary at all since it’s just (i+k)%n places shifted.
    • Solution here: https://gist.github.com/CraigRodrigues/8796843d86dd61423b155f554e9e8ff5
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

// https://www.hackerrank.com/challenges/circular-array-rotation

int main(void)
{
    int n, k, q;
    scanf("%d %d %d", &n, &k, &q);

    int arr[n];
    for(int i = 0; i < n; i++){
       scanf("%d",&arr[i]);
    }

    int toprint[q];
    for(int i = 0; i < q; i++){
       scanf("%d",&toprint[i]);
    }

    int arr2[n];

    for(int i = 0; i < n; i++){
       arr2[(i+k)%n] = arr[i];
    }

    for(int i = 0; i < q; i++){
        printf("%d\n", arr2[(toprint[i])]);
    }
}

 

I enrolled in the Learning How to Learn course.

Learning to Code: Week 13 - Specialize

Learning to Code: Week 11 - Coding While Travelling