見出し画像

CS50 2023 - Week2 Arrays


概要

Week2では、C言語の基礎をさらに深掘りします。
講義の主な内容は、プリプロセッシング、コンパイリング、アセンブリング、リンキング、デバッグ、配列、文字列、コマンドライン引数、そして暗号技術についてです。

Arrays配列を意味します。
配列は、同じ型のデータをひとつの変数名でまとめて格納するデータ構造です。各データは、インデックスによって個別にアクセスできます。

例えば、C言語で整数の配列を宣言する場合、次のようになります。

int numbers[5] = {1, 2, 3, 4, 5};

この例では、numbersという名前の配列が宣言され、整数型のデータ5つ(1, 2, 3, 4, 5)が格納されています。numbers[0]で最初の要素に、numbers[4]で最後の要素にアクセスできます。


Lab 2

Scrabble

スクラブルというゲームをプログラムでシミュレートします。

スクラブルでは、プレイヤーが単語を作ってポイントを獲得します。単語のポイントは、その単語に含まれる各文字のポイントの合計です。

文字とポイントの対応表

例えば、"Code"という単語のスコアは、C3ポイントo1ポイントd2ポイントe1ポイントなので、合計7ポイントです。

今回のLabでは、2人のプレイヤーがそれぞれの単語を入力し、スコアの高いプレイヤーが勝つという短いスクラブルのゲームを実装します。

以下は私が提出したコードです。
TODOのコメントが入っている箇所以外は最初から実装済みなので対応不要です。作業に躓いた場合は、Labのページ内のNot sure how to solve?の動画でほとんど解説されていますので、視聴してみてください。

#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);

int main(void)
{
    // Get input words from both players
    string word[2];
    word[0] = get_string("Player 1: ");
    word[1] = get_string("Player 2: ");

    // Score both words
    int score1 = compute_score(word[0]);
    int score2 = compute_score(word[1]);

    // TODO: Print the winner
    if (score1 > score2)
    {
        printf("Player 1 Wins!");
    }

    if (score1 < score2)
    {
        printf("Player 2 Wins!");
    }

    else if (score1 == score2)
    {
        printf("Tie!!");
    }
}

int compute_score(string word)
{
    // TODO: Compute and return score for string
    int score = 0;
    for (int i = 0; i < strlen(word); i++)
    {
        if (isupper(word[i]))
        {
            score += POINTS[word[i] - 'A'];
        }
        else if (islower(word[i]))
        {
            score += POINTS[word[i] - 'a'];
        }
    }
    return score;
}

Problem Set 2

Week2のProblem Setは、Readabilityと以下の課題からひとつ選び、計2つの課題を提出します。

  • Bulbs (less comfortable)

  • Caesar (less comfortable)

  • Substitution (more comfortable)

  • Wordle50 (more comfortable)

本ページでは、Bulbsを取り上げます。


Readability

読解レベル(テキストの読みやすさ)を算出するプログラムを実装します。
読解レベルは通常、専門家が本を読んで判断しますが、アルゴリズムでも同様のことができます。

読解レベルを算出すための指標として、Coleman-Liau indexを使用します。
この指標は、テキスト中の平均的な文字数や文数に基づいて、テキストの読解レベルを算出します。具体的な計算式は以下の通りです。

index = 0.0588 * L - 0.296 * S - 15.8

Lはテキスト中の100語あたりの文字数、Sはテキスト中の100語あたりの文数です。

プログラムは以下の条件を満たす必要があります。

  • 文字はaからzまでの小文字またはAからZまでの大文字とする。

  • 単語はスペースで区切られた文字列とする。

  • 文の終わりは、ピリオド、感嘆符、疑問符で示す。

以下は私が提出したコードです。

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

int main(void)
{
    // Prompt for user input
    string text = get_string("Text: ");

    // String length
    int i = strlen(text);
    int letters = 0;
    // Initialize words to 1
    int words = 1;
    int sentences = 0;

    // Loop for counting
    for (int x = 0; x < i; x++)
    {
        // Letter counting
        char c = text[x];
        if (isalpha(c) != 0)
        {
            letters++;
        }

        // Word counting
        if (c == ' ')
        {
            words++;
        }

        // Sentence counting
        if (c == '.' || c == '!' || c == '?')
        {
            sentences++;
        }
    }

    // Calculation
    float L = ((float) letters / (float) words) * 100;
    float s = ((float) sentences / (float) words) * 100;
    float subindex = 0.0588 * L - 0.296 * s - 15.8;
    int index = round(subindex);
    if (index > 16)
    {
        printf("Grade 16+\n");
    }
    else if (index < 1)
    {
        printf("Before Grade 1\n");
    }
    else
    {
        printf("Grade %i\n", index);
    }
}

Bulbs

テキストをバイナリ形式に変換するプログラムを作成します。
Bulbは電球のことです。電球の"オン""オフ"で、"0"と"1"を表現します。

変換は以下の順で行います。
※テキストからの変換はASCIIコードを使用します

テキスト→10進数の数値→2進数の数値→電球のオフオン

講義等でも紹介されている"HI!"の場合は以下のようになります。

  • テキスト:H、I、!

  • 10進数:72、73、33

  • 2進数:01001000、01001001、00100001

電球(黒はオフ、黄色はオン)

以下は私が提出したコードです。

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

const int BITS_IN_BYTE = 8;

void print_bulb(int bit);

int main(void)
{
    string message = get_string("Message: ");

    // Process each character in the string
    for (int i = 0, n = strlen(message); i < n; i++)
    {
        char c = message[i];
        int ascii_value = (int) c; // Get the ASCII value of the character

        // Convert to 8-bit binary and print
        for (int j = 7; j >= 0; j--)
        {
            int bit = (ascii_value >> j) & 1; // Get the value of j-th bit
            print_bulb(bit);
        }

        printf("\n");
    }

    return 0;
}

void print_bulb(int bit)
{
    if (bit == 0)
    {
        // Dark emoji
        printf("\U000026AB");
    }
    else if (bit == 1)
    {
        // Light emoji
        printf("\U0001F7E1");
    }
}

さいごに

Week2は比較的シンプルな内容ですが、何か不明点や質問などあれば、コメントをいただけますと幸甚です。


この記事が気に入ったらサポートをしてみませんか?