added psets
@ -0,0 +1,65 @@
|
|||||||
|
#include <cs50.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, string argv[])
|
||||||
|
{
|
||||||
|
// Make sure program was run with just one command-line argument
|
||||||
|
if (argc > 2 || argc < 2)
|
||||||
|
{
|
||||||
|
printf("Usage: ./caesar {key}\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure every character in argv[1] is a digit
|
||||||
|
for (int i = 0; i < strlen(argv[1]); i++)
|
||||||
|
{
|
||||||
|
if (!isdigit(argv[1][i]))
|
||||||
|
{
|
||||||
|
printf("Usage: ./caesar {key}\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert argv[1] from a `string` to an `int`
|
||||||
|
int key = atoi(argv[1]);
|
||||||
|
|
||||||
|
// Prompt user for plaintext
|
||||||
|
string plaintext = get_string("plaintext: ");
|
||||||
|
|
||||||
|
// For each character in the plaintext:
|
||||||
|
string ciphertext = plaintext;
|
||||||
|
for (int i = 0; i < strlen(plaintext); i++)
|
||||||
|
{
|
||||||
|
if (isalpha(plaintext[i]))
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
// Rotate the character if it's a letter
|
||||||
|
char plaintextChar = (char) plaintext[i];
|
||||||
|
if (isupper(plaintextChar))
|
||||||
|
{
|
||||||
|
n = 65;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = 97;
|
||||||
|
}
|
||||||
|
int plainAlphaIndex = (int) plaintextChar - n;
|
||||||
|
int cipherAlphaIndex = (plainAlphaIndex + key) % 26;
|
||||||
|
char ciphertextChar = (char) cipherAlphaIndex + n;
|
||||||
|
// printf("pT = %c, pAI = %i, cAI = %i, cT = %c", plaintextChar, plainAlphaIndex,
|
||||||
|
// cipherAlphaIndex, ciphertextChar);
|
||||||
|
ciphertext[i] = ciphertextChar;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ciphertext[i] = plaintext[i];
|
||||||
|
}
|
||||||
|
// printf("\n");
|
||||||
|
}
|
||||||
|
printf("ciphertext: %s", ciphertext);
|
||||||
|
printf("\n\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
#include <cs50.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int count_letters(string text);
|
||||||
|
int count_words(string text);
|
||||||
|
int count_sentences(string text);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Prompt the user for some text
|
||||||
|
string text = get_string("Text: ");
|
||||||
|
|
||||||
|
int words = 1;
|
||||||
|
int sentences = 0;
|
||||||
|
int letters = 0;
|
||||||
|
|
||||||
|
// Count the number of letters, words, and sentences in the text
|
||||||
|
for (int i = 0, n = strlen(text); i < n; i++)
|
||||||
|
{
|
||||||
|
if (text[i] == ' ')
|
||||||
|
{
|
||||||
|
words += 1;
|
||||||
|
}
|
||||||
|
else if (text[i] == '.' || text[i] == '!' || text[i] == '?')
|
||||||
|
{
|
||||||
|
sentences += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isalpha(text[i]))
|
||||||
|
{
|
||||||
|
letters += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("Letters: %i\n", letters);
|
||||||
|
// printf("Words: %i\n", words);
|
||||||
|
// printf("Sentences: %i\n", sentences);
|
||||||
|
|
||||||
|
// Compute the Coleman-Liau index
|
||||||
|
float L = (float) letters / (float) words * 100;
|
||||||
|
float S = (float) sentences / (float) words * 100;
|
||||||
|
float X = 0.0588 * L - 0.296 * S - 15.8;
|
||||||
|
int Xint = (int) round(X);
|
||||||
|
// printf("L=%f, S=%f, X=%f, Xint=%i", L, S, X, Xint);
|
||||||
|
|
||||||
|
// Print the grade level
|
||||||
|
if (Xint >= 16)
|
||||||
|
{
|
||||||
|
printf("Grade 16+\n");
|
||||||
|
}
|
||||||
|
else if (Xint < 1)
|
||||||
|
{
|
||||||
|
printf("Before Grade 1\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Grade %i\n", Xint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_letters(string text)
|
||||||
|
{
|
||||||
|
// Return the number of letters in text
|
||||||
|
int letters = 0;
|
||||||
|
for (int i = 0, n = strlen(text); i < n; i++)
|
||||||
|
{
|
||||||
|
if (isalpha(text[i]))
|
||||||
|
{
|
||||||
|
letters += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return letters;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_words(string text)
|
||||||
|
{
|
||||||
|
// Return the number of words in text
|
||||||
|
int words = 0;
|
||||||
|
for (int i = 0, n = strlen(text); i < n; i++)
|
||||||
|
{
|
||||||
|
if (text[i] == ' ' && (text[i - 1] != '.' || text[i - 1] != '!' || text[i - 1] != '?'))
|
||||||
|
{
|
||||||
|
words += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return words;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_sentences(string text)
|
||||||
|
{
|
||||||
|
// Return the number of sentences in text
|
||||||
|
int sentences = 0;
|
||||||
|
for (int i = 0, n = strlen(text); i < n; i++)
|
||||||
|
{
|
||||||
|
if (text[i] == '.' || text[i] == '!' || text[i] == '?')
|
||||||
|
{
|
||||||
|
sentences += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sentences;
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
#include <cs50.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Points assigned to each letter of the alphabet
|
||||||
|
int POINTS[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};
|
||||||
|
|
||||||
|
int compute_score(string word)
|
||||||
|
{
|
||||||
|
// Keep track of score
|
||||||
|
int score = 0;
|
||||||
|
|
||||||
|
// Compute score for each character
|
||||||
|
for (int i = 0, len = strlen(word); i < len; i++)
|
||||||
|
{
|
||||||
|
if (isupper(word[i]))
|
||||||
|
{
|
||||||
|
score += POINTS[word[i] - 'A'];
|
||||||
|
}
|
||||||
|
else if (islower(word[i]))
|
||||||
|
{
|
||||||
|
score += POINTS[word[i] - 'a'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Prompt the user for two words
|
||||||
|
string word1 = get_string("Player 1: ");
|
||||||
|
string word2 = get_string("Player 2: ");
|
||||||
|
|
||||||
|
// Compute the score of each word
|
||||||
|
int score1 = compute_score(word1);
|
||||||
|
int score2 = compute_score(word2);
|
||||||
|
|
||||||
|
// Print the winner
|
||||||
|
if (score1 > score2)
|
||||||
|
{
|
||||||
|
printf("Player 1 wins!\n");
|
||||||
|
}
|
||||||
|
else if (score1 < score2)
|
||||||
|
{
|
||||||
|
printf("Player 2 wins!\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Tie!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
#include <cs50.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Max number of candidates
|
||||||
|
#define MAX 9
|
||||||
|
|
||||||
|
// Candidates have name and vote count
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
int votes;
|
||||||
|
} candidate;
|
||||||
|
|
||||||
|
// Array of candidates
|
||||||
|
candidate candidates[MAX];
|
||||||
|
|
||||||
|
// Number of candidates
|
||||||
|
int candidate_count;
|
||||||
|
|
||||||
|
// Function prototypes
|
||||||
|
bool vote(string name);
|
||||||
|
void print_winner(void);
|
||||||
|
|
||||||
|
int main(int argc, string argv[])
|
||||||
|
{
|
||||||
|
// Check for invalid usage
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("Usage: plurality [candidate ...]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate array of candidates
|
||||||
|
candidate_count = argc - 1;
|
||||||
|
if (candidate_count > MAX)
|
||||||
|
{
|
||||||
|
printf("Maximum number of candidates is %i\n", MAX);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
candidates[i].name = argv[i + 1];
|
||||||
|
candidates[i].votes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int voter_count = get_int("Number of voters: ");
|
||||||
|
|
||||||
|
// Loop over all voters
|
||||||
|
for (int i = 0; i < voter_count; i++)
|
||||||
|
{
|
||||||
|
string name = get_string("Vote: ");
|
||||||
|
|
||||||
|
// Check for invalid vote
|
||||||
|
if (!vote(name))
|
||||||
|
{
|
||||||
|
printf("Invalid vote.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display winner of election
|
||||||
|
print_winner();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update vote totals given a new vote
|
||||||
|
bool vote(string name)
|
||||||
|
{
|
||||||
|
// Iterate over each candidate
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
// Check if candidate's name matches given name
|
||||||
|
if (strcmp(candidates[i].name, name) == 0)
|
||||||
|
{
|
||||||
|
// If yes, increment candidate's votes and return true
|
||||||
|
candidates[i].votes += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If no match, return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the winner (or winners) of the election
|
||||||
|
void print_winner(void)
|
||||||
|
{
|
||||||
|
// Find the maximum number of votes
|
||||||
|
int max = 0;
|
||||||
|
int winnerCount = 0;
|
||||||
|
candidate winners[MAX];
|
||||||
|
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (candidates[i].votes > max)
|
||||||
|
{
|
||||||
|
// Found new max and save the candidate only
|
||||||
|
// printf("%s has the most votes currently!\n", candidates[i].name);
|
||||||
|
winnerCount = 0;
|
||||||
|
winners[0] = candidates[i];
|
||||||
|
max = candidates[i].votes;
|
||||||
|
}
|
||||||
|
else if (candidates[i].votes == max)
|
||||||
|
{
|
||||||
|
// Found new equal max and save the candidate addtl
|
||||||
|
winnerCount += 1;
|
||||||
|
// printf("%s has the equal votes compared to %s!\n", candidates[i].name, winners[winnerCount -1].name);
|
||||||
|
winners[winnerCount] = candidates[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the candidate (or candidates) with maximum votes
|
||||||
|
for (int i = 0; i <= winnerCount; i++)
|
||||||
|
{
|
||||||
|
printf("%s\n", winners[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
@ -0,0 +1,219 @@
|
|||||||
|
#include <cs50.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Max voters and candidates
|
||||||
|
#define MAX_VOTERS 100
|
||||||
|
#define MAX_CANDIDATES 9
|
||||||
|
|
||||||
|
// preferences[i][j] is jth preference for voter i
|
||||||
|
int preferences[MAX_VOTERS][MAX_CANDIDATES];
|
||||||
|
|
||||||
|
// Candidates have name, vote count, eliminated status
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
int votes;
|
||||||
|
bool eliminated;
|
||||||
|
} candidate;
|
||||||
|
|
||||||
|
// Array of candidates
|
||||||
|
candidate candidates[MAX_CANDIDATES];
|
||||||
|
|
||||||
|
// Numbers of voters and candidates
|
||||||
|
int voter_count;
|
||||||
|
int candidate_count;
|
||||||
|
|
||||||
|
// Function prototypes
|
||||||
|
bool vote(int voter, int rank, string name);
|
||||||
|
void tabulate(void);
|
||||||
|
bool print_winner(void);
|
||||||
|
int find_min(void);
|
||||||
|
bool is_tie(int min);
|
||||||
|
void eliminate(int min);
|
||||||
|
|
||||||
|
int main(int argc, string argv[])
|
||||||
|
{
|
||||||
|
// Check for invalid usage
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("Usage: runoff [candidate ...]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate array of candidates
|
||||||
|
candidate_count = argc - 1;
|
||||||
|
if (candidate_count > MAX_CANDIDATES)
|
||||||
|
{
|
||||||
|
printf("Maximum number of candidates is %i\n", MAX_CANDIDATES);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
candidates[i].name = argv[i + 1];
|
||||||
|
candidates[i].votes = 0;
|
||||||
|
candidates[i].eliminated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
voter_count = get_int("Number of voters: ");
|
||||||
|
if (voter_count > MAX_VOTERS)
|
||||||
|
{
|
||||||
|
printf("Maximum number of voters is %i\n", MAX_VOTERS);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep querying for votes
|
||||||
|
for (int i = 0; i < voter_count; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Query for each rank
|
||||||
|
for (int j = 0; j < candidate_count; j++)
|
||||||
|
{
|
||||||
|
string name = get_string("Rank %i: ", j + 1);
|
||||||
|
|
||||||
|
// Record vote, unless it's invalid
|
||||||
|
if (!vote(i, j, name))
|
||||||
|
{
|
||||||
|
printf("Invalid vote.\n");
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep holding runoffs until winner exists
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Calculate votes given remaining candidates
|
||||||
|
tabulate();
|
||||||
|
|
||||||
|
// Check if election has been won
|
||||||
|
bool won = print_winner();
|
||||||
|
if (won)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminate last-place candidates
|
||||||
|
int min = find_min();
|
||||||
|
bool tie = is_tie(min);
|
||||||
|
|
||||||
|
// If tie, everyone wins
|
||||||
|
if (tie)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (!candidates[i].eliminated)
|
||||||
|
{
|
||||||
|
printf("%s\n", candidates[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminate anyone with minimum number of votes
|
||||||
|
eliminate(min);
|
||||||
|
|
||||||
|
// Reset vote counts back to zero
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
candidates[i].votes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record preference if vote is valid
|
||||||
|
bool vote(int voter, int rank, string name)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(name, candidates[i].name) == 0)
|
||||||
|
{
|
||||||
|
preferences[voter][rank] = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tabulate votes for non-eliminated candidates
|
||||||
|
void tabulate(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < voter_count; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < candidate_count; j++)
|
||||||
|
{
|
||||||
|
if (!candidates[preferences[i][j]].eliminated)
|
||||||
|
{
|
||||||
|
candidates[preferences[i][j]].votes += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the winner of the election, if there is one
|
||||||
|
bool print_winner(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (!candidates[i].eliminated && candidates[i].votes > voter_count / 2)
|
||||||
|
{
|
||||||
|
printf("%s\n", candidates[i].name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the minimum number of votes any remaining candidate has
|
||||||
|
int find_min(void)
|
||||||
|
{
|
||||||
|
int lastMin = MAX_VOTERS;
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (!candidates[i].eliminated)
|
||||||
|
{
|
||||||
|
if (candidates[i].votes < lastMin)
|
||||||
|
{
|
||||||
|
lastMin = candidates[i].votes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if the election is tied between all candidates, false otherwise
|
||||||
|
bool is_tie(int min)
|
||||||
|
{
|
||||||
|
int candidates_in = 0;
|
||||||
|
int candidates_tied = 0;
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (!candidates[i].eliminated)
|
||||||
|
{
|
||||||
|
candidates_in += 1;
|
||||||
|
if (candidates[i].votes == min)
|
||||||
|
{
|
||||||
|
candidates_tied += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (candidates_tied == candidates_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminate the candidate (or candidates) in last place
|
||||||
|
void eliminate(int min)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < candidate_count; i++)
|
||||||
|
{
|
||||||
|
if (candidates[i].votes == min)
|
||||||
|
{
|
||||||
|
candidates[i].eliminated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
sort1 uses: Bubble Sort
|
||||||
|
|
||||||
|
How do you know?: slowest, but fast with sorted
|
||||||
|
|
||||||
|
sort2 uses: Merge Sort
|
||||||
|
|
||||||
|
How do you know?: fastest, especially with reversed or random
|
||||||
|
|
||||||
|
sort3 uses: Selection Sort
|
||||||
|
|
||||||
|
How do you know?: fast with random, but slow with reversed
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
filter:
|
||||||
|
clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -lm -o filter filter.c helpers.c
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
// BMP-related data types based on Microsoft's own
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// These data types are essentially aliases for C/C++ primitive data types.
|
||||||
|
// Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
|
||||||
|
// See https://en.wikipedia.org/wiki/C_data_types#stdint.h for more on stdint.h.
|
||||||
|
|
||||||
|
typedef uint8_t BYTE;
|
||||||
|
typedef uint32_t DWORD;
|
||||||
|
typedef int32_t LONG;
|
||||||
|
typedef uint16_t WORD;
|
||||||
|
|
||||||
|
// The BITMAPFILEHEADER structure contains information about the type, size,
|
||||||
|
// and layout of a file that contains a DIB [device-independent bitmap].
|
||||||
|
// Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WORD bfType;
|
||||||
|
DWORD bfSize;
|
||||||
|
WORD bfReserved1;
|
||||||
|
WORD bfReserved2;
|
||||||
|
DWORD bfOffBits;
|
||||||
|
} __attribute__((__packed__))
|
||||||
|
BITMAPFILEHEADER;
|
||||||
|
|
||||||
|
// The BITMAPINFOHEADER structure contains information about the
|
||||||
|
// dimensions and color format of a DIB [device-independent bitmap].
|
||||||
|
// Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD biSize;
|
||||||
|
LONG biWidth;
|
||||||
|
LONG biHeight;
|
||||||
|
WORD biPlanes;
|
||||||
|
WORD biBitCount;
|
||||||
|
DWORD biCompression;
|
||||||
|
DWORD biSizeImage;
|
||||||
|
LONG biXPelsPerMeter;
|
||||||
|
LONG biYPelsPerMeter;
|
||||||
|
DWORD biClrUsed;
|
||||||
|
DWORD biClrImportant;
|
||||||
|
} __attribute__((__packed__))
|
||||||
|
BITMAPINFOHEADER;
|
||||||
|
|
||||||
|
// The RGBTRIPLE structure describes a color consisting of relative intensities of
|
||||||
|
// red, green, and blue. Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
BYTE rgbtBlue;
|
||||||
|
BYTE rgbtGreen;
|
||||||
|
BYTE rgbtRed;
|
||||||
|
} __attribute__((__packed__))
|
||||||
|
RGBTRIPLE;
|
||||||
@ -0,0 +1,150 @@
|
|||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// Define allowable filters
|
||||||
|
char *filters = "bgrs";
|
||||||
|
|
||||||
|
// Get filter flag and check validity
|
||||||
|
char filter = getopt(argc, argv, filters);
|
||||||
|
if (filter == '?')
|
||||||
|
{
|
||||||
|
printf("Invalid filter.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure only one filter
|
||||||
|
if (getopt(argc, argv, filters) != -1)
|
||||||
|
{
|
||||||
|
printf("Only one filter allowed.\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure proper usage
|
||||||
|
if (argc != optind + 2)
|
||||||
|
{
|
||||||
|
printf("Usage: ./filter [flag] infile outfile\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember filenames
|
||||||
|
char *infile = argv[optind];
|
||||||
|
char *outfile = argv[optind + 1];
|
||||||
|
|
||||||
|
// Open input file
|
||||||
|
FILE *inptr = fopen(infile, "r");
|
||||||
|
if (inptr == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not open %s.\n", infile);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open output file
|
||||||
|
FILE *outptr = fopen(outfile, "w");
|
||||||
|
if (outptr == NULL)
|
||||||
|
{
|
||||||
|
fclose(inptr);
|
||||||
|
printf("Could not create %s.\n", outfile);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read infile's BITMAPFILEHEADER
|
||||||
|
BITMAPFILEHEADER bf;
|
||||||
|
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
|
||||||
|
|
||||||
|
// Read infile's BITMAPINFOHEADER
|
||||||
|
BITMAPINFOHEADER bi;
|
||||||
|
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
|
||||||
|
|
||||||
|
// Ensure infile is (likely) a 24-bit uncompressed BMP 4.0
|
||||||
|
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || bi.biBitCount != 24 ||
|
||||||
|
bi.biCompression != 0)
|
||||||
|
{
|
||||||
|
fclose(outptr);
|
||||||
|
fclose(inptr);
|
||||||
|
printf("Unsupported file format.\n");
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get image's dimensions
|
||||||
|
int height = abs(bi.biHeight);
|
||||||
|
int width = bi.biWidth;
|
||||||
|
|
||||||
|
// Allocate memory for image
|
||||||
|
RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
|
||||||
|
if (image == NULL)
|
||||||
|
{
|
||||||
|
printf("Not enough memory to store image.\n");
|
||||||
|
fclose(outptr);
|
||||||
|
fclose(inptr);
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine padding for scanlines
|
||||||
|
int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4;
|
||||||
|
|
||||||
|
// Iterate over infile's scanlines
|
||||||
|
for (int i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
// Read row into pixel array
|
||||||
|
fread(image[i], sizeof(RGBTRIPLE), width, inptr);
|
||||||
|
|
||||||
|
// Skip over padding
|
||||||
|
fseek(inptr, padding, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter image
|
||||||
|
switch (filter)
|
||||||
|
{
|
||||||
|
// Blur
|
||||||
|
case 'b':
|
||||||
|
blur(height, width, image);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Grayscale
|
||||||
|
case 'g':
|
||||||
|
grayscale(height, width, image);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Reflection
|
||||||
|
case 'r':
|
||||||
|
reflect(height, width, image);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Sepia
|
||||||
|
case 's':
|
||||||
|
sepia(height, width, image);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write outfile's BITMAPFILEHEADER
|
||||||
|
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
|
||||||
|
|
||||||
|
// Write outfile's BITMAPINFOHEADER
|
||||||
|
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
|
||||||
|
|
||||||
|
// Write new pixels to outfile
|
||||||
|
for (int i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
// Write row to outfile
|
||||||
|
fwrite(image[i], sizeof(RGBTRIPLE), width, outptr);
|
||||||
|
|
||||||
|
// Write padding at end of row
|
||||||
|
for (int k = 0; k < padding; k++)
|
||||||
|
{
|
||||||
|
fputc(0x00, outptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free memory for image
|
||||||
|
free(image);
|
||||||
|
|
||||||
|
// Close files
|
||||||
|
fclose(inptr);
|
||||||
|
fclose(outptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
#include "helpers.h"
|
||||||
|
#include <cs50.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
int RoundCastCap(float color);
|
||||||
|
|
||||||
|
// Convert image to grayscale
|
||||||
|
void grayscale(int height, int width, RGBTRIPLE image[height][width])
|
||||||
|
{
|
||||||
|
// Loop over all pixels
|
||||||
|
for (int i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
// Take average of red, green, and blue
|
||||||
|
int average = (int) round(((float) image[i][j].rgbtRed + (float) image[i][j].rgbtGreen +
|
||||||
|
(float) image[i][j].rgbtBlue) /
|
||||||
|
3.0);
|
||||||
|
// Update pixel values
|
||||||
|
image[i][j].rgbtRed = average;
|
||||||
|
image[i][j].rgbtGreen = average;
|
||||||
|
image[i][j].rgbtBlue = average;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert image to sepia
|
||||||
|
void sepia(int height, int width, RGBTRIPLE image[height][width])
|
||||||
|
{
|
||||||
|
// Loop over all pixels
|
||||||
|
for (int i = 0; i < heightbuffer; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
// Get original colors
|
||||||
|
int originalRed = image[i][j].rgbtRed;
|
||||||
|
int originalGreen = image[i][j].rgbtGreen;
|
||||||
|
int originalBlue = image[i][j].rgbtBlue;
|
||||||
|
// Compute sepia values
|
||||||
|
float sepiaRed = .393 * originalRed + .769 * originalGreen + .189 * originalBlue;
|
||||||
|
float sepiaGreen = .349 * originalRed + .686 * originalGreen + .168 * originalBlue;
|
||||||
|
float sepiaBlue = .272 * originalRed + .534 * originalGreen + .131 * originalBlue;
|
||||||
|
// Round, cast and cap between 0 and 255
|
||||||
|
int sepiaRedInt = RoundCastCap(sepiaRed);
|
||||||
|
int sepiaGreenInt = RoundCastCap(sepiaGreen);
|
||||||
|
int sepiaBlueInt = RoundCastCap(sepiaBlue);
|
||||||
|
|
||||||
|
// Update pixel values
|
||||||
|
image[i][j].rgbtRed = sepiaRedInt;
|
||||||
|
image[i][j].rgbtGreen = sepiaGreenInt;
|
||||||
|
image[i][j].rgbtBlue = sepiaBlueInt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect image horizontally
|
||||||
|
void reflect(int height, int width, RGBTRIPLE image[height][width])
|
||||||
|
{
|
||||||
|
// Copy complete image
|
||||||
|
RGBTRIPLE image_copy[height][width];
|
||||||
|
for (int i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
image_copy[i][j] = image[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop over all pixels
|
||||||
|
for (int k = 0; k < height; k++)
|
||||||
|
{
|
||||||
|
for (int l = 0; l < width / 2; l++)
|
||||||
|
{
|
||||||
|
image[k][l] = image_copy[k][width - l - 1];
|
||||||
|
image[k][width - l - 1] = image_copy[k][l];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blur image
|
||||||
|
void blur(int height, int width, RGBTRIPLE image[height][width])
|
||||||
|
{
|
||||||
|
RGBTRIPLE blurred_image[height][width];
|
||||||
|
|
||||||
|
for (int col = 0; col < height; col++)
|
||||||
|
{
|
||||||
|
for (int row = 0; row < width; row++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double sumRed = 0;
|
||||||
|
double sumGreen = 0;
|
||||||
|
double sumBlue = 0;
|
||||||
|
double divider = 0;
|
||||||
|
|
||||||
|
for (int y = col - 1; y <= col + 1; y++)
|
||||||
|
{
|
||||||
|
for (int x = row - 1; x <= row + 1; x++)
|
||||||
|
{
|
||||||
|
// If a pixel is within a valid range
|
||||||
|
if ((y >= 0 && y < height) && (x >= 0 && x < width))
|
||||||
|
{
|
||||||
|
sumRed = image[y][x].rgbtRed + sumRed;
|
||||||
|
sumGreen = image[y][x].rgbtGreen + sumGreen;
|
||||||
|
sumBlue = image[y][x].rgbtBlue + sumBlue;
|
||||||
|
divider++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blurred_image[col][row].rgbtRed = round((sumRed / divider));
|
||||||
|
blurred_image[col][row].rgbtGreen = round((sumGreen / divider));
|
||||||
|
blurred_image[col][row].rgbtBlue = round((sumBlue / divider));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the orinal image with the blurred image
|
||||||
|
for (int i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < width; j++)
|
||||||
|
{
|
||||||
|
image[i][j].rgbtRed = blurred_image[i][j].rgbtRed;
|
||||||
|
image[i][j].rgbtGreen = blurred_image[i][j].rgbtGreen;
|
||||||
|
image[i][j].rgbtBlue = blurred_image[i][j].rgbtBlue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round, cast and cap between 0 and 255
|
||||||
|
int RoundCastCap(float color)
|
||||||
|
{
|
||||||
|
int colorInt = (int) round(color);
|
||||||
|
if (colorInt > 255)
|
||||||
|
{
|
||||||
|
colorInt = 255;
|
||||||
|
}
|
||||||
|
else if (colorInt < 0)
|
||||||
|
{
|
||||||
|
colorInt = 0;
|
||||||
|
}
|
||||||
|
return colorInt;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
#include "bmp.h"
|
||||||
|
|
||||||
|
// Convert image to grayscale
|
||||||
|
void grayscale(int height, int width, RGBTRIPLE image[height][width]);
|
||||||
|
|
||||||
|
// Convert image to sepia
|
||||||
|
void sepia(int height, int width, RGBTRIPLE image[height][width]);
|
||||||
|
|
||||||
|
// Reflect image horizontally
|
||||||
|
void reflect(int height, int width, RGBTRIPLE image[height][width]);
|
||||||
|
|
||||||
|
// Blur image
|
||||||
|
void blur(int height, int width, RGBTRIPLE image[height][width]);
|
||||||
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 703 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,55 @@
|
|||||||
|
#include <cs50.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// Accept a single command-line argument
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
printf("Usage: ./recover FILE\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the memory card
|
||||||
|
FILE *inptr = fopen(argv[1], "r");
|
||||||
|
if (inptr == NULL)
|
||||||
|
{
|
||||||
|
printf("Unable to open file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a buffer for a block of data
|
||||||
|
uint8_t buffer[512];
|
||||||
|
int block_counter = 0;
|
||||||
|
FILE *outptr = NULL;
|
||||||
|
char filename[8];
|
||||||
|
|
||||||
|
// While there's still data left to read from the memory card
|
||||||
|
int i = 0;
|
||||||
|
while (fread(buffer, 1, 512, inptr) == 512)
|
||||||
|
{
|
||||||
|
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff &&
|
||||||
|
(buffer[3] & 0xf0) == 0xe0)
|
||||||
|
{
|
||||||
|
if (outptr != 0)
|
||||||
|
{
|
||||||
|
fclose(outptr);
|
||||||
|
}
|
||||||
|
sprintf(filename, "%03i.jpg", block_counter);
|
||||||
|
outptr = fopen(filename, "w");
|
||||||
|
block_counter++;
|
||||||
|
}
|
||||||
|
if (outptr != 0)
|
||||||
|
{
|
||||||
|
// if already found, continue writing
|
||||||
|
fwrite(buffer, 512, 1, outptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(inptr);
|
||||||
|
fclose(outptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
// Modifies the volume of an audio file
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// Number of bytes in .wav header
|
||||||
|
const int HEADER_SIZE = 44;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// Check command-line arguments
|
||||||
|
if (argc != 4)
|
||||||
|
{
|
||||||
|
printf("Usage: ./volume input.wav output.wav factor\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open files and determine scaling factor
|
||||||
|
FILE *input = fopen(argv[1], "r");
|
||||||
|
if (input == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not open file.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *output = fopen(argv[2], "w");
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not open file.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float factor = atof(argv[3]);
|
||||||
|
|
||||||
|
// Copy header from input file to output file
|
||||||
|
uint8_t header[HEADER_SIZE];
|
||||||
|
fread(header, HEADER_SIZE, 1, input);
|
||||||
|
fwrite(header, HEADER_SIZE, 1, output);
|
||||||
|
|
||||||
|
// Read samples from input file and write updated data to output file
|
||||||
|
int16_t buffer;
|
||||||
|
while (fread(&buffer, sizeof(int16_t), 1, input))
|
||||||
|
{
|
||||||
|
buffer *= factor;
|
||||||
|
fwrite(&buffer, sizeof(int16_t), 1, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close files
|
||||||
|
fclose(input);
|
||||||
|
fclose(output);
|
||||||
|
}
|
||||||