20210124のJavaに関する記事は8件です。

【Java】Date型の日時を計算する方法

プログラミング勉強日記

2021年1月24日
JavaでDate型の日時を計算する方法を示す。

Date型とは

 Javaで日時の処理をするために定義されたデータ型で、日時情報は1970年1月1日0時からの経過時間をミリ秒で表したものである。

Date型を使った日付の取得
// 2021年1月24日日曜日 22時56分12秒
Sun Jan 18 22:55:12 JST 2021

Calendarクラスとは

 CalendarクラスはDate型と同様日時を扱うデータ型で、Date型よりも細かい日時演算ができる。Date型の演算を行う場合はCalendar型に変換して、演算処理を行う。

Date型をCalendar型に変換する方法
Calendar Calendar型オブジェクト名 = Calendar.getInstance();

Calendar型オブジェクト名.setTime(Date);
Calendar型からDate型を取得する方法
Date型オブジェクト名 = Calendar型オブジェクト名.getTime();

Date型の日時を加減算する方法

 Date型ので日時を加減算するためにはCalendar型のaddメソッドを使う。加算する場合は、第二引数で正の整数を指定する。減算する場合は第2引数に負の整数を指定する。

日付を加算する方法
Calendar型.add(年月日時間などを指定, );

// 第1引数で渡すもの
Calendar.YEAR            // 年
Calendar.MONTH           // 月
Calendar.DAY_OF_MONTH    // 日
Calendar.HOUR_OF_DAY     // 時間
Calendar.MINUTE          // 分
// 1日先の日付を取得したいとき
Calendar型.add(Calendar.DAY_OF_MONTH, 1);

// 2ヵ月前の日付を取得したいとき
Calendar型.add(Calendar.MONTH, -2);

サンプルプログラム

import java.util.Date;
import java.util.Calendar;

class Sample{
        public static void main(String args[]){

                // Date型で現在時刻を取得する
                 Date date = new Date();

                 Calendar calendar = Calendar.getInstance();
                 calendar.setTime(date);

                //Date型の持つ日時を表示
                 System.out.println(date);

                 //Date型の持つ日時の4年後を表示(日時の加算)
                 calendar.add(Calendar.YEAR, 4);
                 date = calendar.getTime();
                 System.out.println(date);

                //Date型の持つ日時の3日前を表示(日時の減算)
                 calendar.add(Calendar.DAY_OF_MONTH, -3);
                 date = calendar.getTime();
                System.out.println(date);

        }
}
実行結果
Sun Jan 24 23:18:33 JST 2021
Fri Jan 24 23:18:33 JST 2025
Tue Jan 21 23:18:33 JST 2025

参考文献

日時を加算/減算する(add)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JSP/サーブレット】 JSPファイルを使ってブラウザに「Hello World」を表示させてみた!

前回の続きになります:train2:

※動的プロジェクトの作成などは、前の記事で紹介しています:raising_hand:

1,JSPファイルの作成:blue_book:

2,保存場所とソースコード:books:

3,サーバーを起動:cat:

サーバー起動(Tomcat)

ブラウザ表示(Google Chrome)

4,振り返り:pencil2:

JSPファイルをブラウザ表示させることができました:blush:

JSPファイルはMVCモデルの中で、V(view)として活躍します:dancer:

URLとリクエストメソッドにも注目すると、

 URL ⇨ localhost:8080/JSP_Servlet/view/index.jsp

 Request Method ⇨ GET

となっています.

サーブレットクラスを起動させた場合とURLに少し違いがあると思います。

URLにも注意しながら学習を進めて下さい:raised_hand:

5,次のステップ:airplane:

次回は、フォワード(forward)を扱います!
要するに、サーブレットクラスからJSPファイルに画面遷移する方法です!

キーワード : RequestDispatcher :mag:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS_WEB3層環境構築③

前回の記事
https://qiita.com/shinichi_yoshioka/items/e358f57a3ecb7735c091
前々回(初回)の記事
https://qiita.com/shinichi_yoshioka/items/7226b9ebaad06c569c80
構成図
構成図_v4.png

前回の続きをやっていく。
VSCodeすら使ったことなかったが、VSCodeの拡張機能にdrawioというものがあって、
カッコ良いアイコンなどが使えるのを教えてもらった。
さっそく使ってみたが、色のセンスはお察しだ。

初回記事ではDBの切り替えをしたいと書いたが、まずは正常な状態を作りたい。
WEBサーバにはリバースプロキシの設定(To:APサーバ)をし、APサーバでJSPを使って、
DBを参照できることを正常な状態とすることにした。

◆リバースプロキシの設定
対象:WEBサーバ
/etc/nginx/conf.d 配下にserver.confというファイルを作る。

cd /etc/nginx/conf.d
vi server.conf

server.confの中身は、APサーバのプライベートアドレス:ポート番号(8080)を指定した。

#server.conf
server{
   location / {
        proxy_pass    http://172.16.3.246:8080/;
    }
}

nginxのサービスを再起動(systemctl restart nginx)して、ブラウザにWEBサーバのパブリックアドレスを入力し、
APサーバのtomcatのページが表示されることを確認した。
[自宅PC]-[Internet]-[WEBサーバ]-[APサーバ] ←ここまでのイメージ
tomcat5.PNG

◆JDBC for MySQLのインストール
対象:APサーバ
APサーバにJDBCドライバーをインストールしようと思ったのだが、AmazonLinux用がなかった^^;;;
ということで、前回作ったAPサーバはぶっ壊して、再度RedHatで作りなおして、Tomcatのインストールまでは済んだとこ。
これがクラウドの良いところである。(オンプレでOS選定ミスってたら、首飛んでた)
EIPを使っていたので、記事の不整合もない!
OSやJavaのバージョン、Tomcatの状態はこんな感じ。
tomcat3.PNG
MySQLコミュニティサーバからJDBCドライバーのRPM(RHEL用)をダウンロードしインストールしようとしたが、
依存関係でopenjdk-headlessが必要と言われた。
yumでopenjdk-headlessをインストール後に、mysql-connector-javaをRPMコマンドでインストールした。

wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.23-1.el8.noarch.rpm
yum install java-1.8.0-openjdk-headless -y
rpm -ivh mysql-connector-java-8.0.23-1.el8.noarch.rpm
rpm -qa | grep mysql

tomcat4.PNG

◆サンプルデータベースの用意
対象:DBサーバ
参照するためのDBを用意するため、以下からworld databaseをインポートすることにした。
https://dev.mysql.com/doc/index-other.html
まずはDBサーバにssh接続し、wgetコマンドにてダウンロードした。
gz形式だったため、gunzipコマンドにて解凍した。

wget https://downloads.mysql.com/docs/world.sql.gz
gunzip world.sql.gz

次にMySQLにログインし、SOURCEコマンドにて、world.sqlをインポートした。

mysql> SOURCE root/world.sql;/r

データベースに"world"がインポートされた。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| TEST               |
| auth               |
| mysql              |
| performance_schema |
| sys                |
| world              |
+--------------------+

データベースをworldに切り替え、テーブルが存在することを確認した。

mysql> use world;

mysql> show tables;
+-----------------+
| Tables_in_world |
+-----------------+
| city            |
| country         |
| countrylanguage |
+-----------------+
3 rows in set (0.00 sec)

MySQLはデフォルトで、外部からのアクセスを許可されていないため、
以下の権限追加をした。
権限追加後は、FLUSHにて権限を再読み込みした。
※*(すべてのデータベース).*(すべてのテーブル)を認識できるようにユーザ名@接続元IPアドレス(APサーバ)へ権限を与える

mysql> GRANT all ON *.* TO root@'172.16.3.246' IDENTIFIED BY 'MySQLのパスワード';     
mysql> FLUSH PRIVILEGES;    ←権限関係の再読み込み

◆JDBCドライバの配置とサンプルJSPの作成
対象:APサーバ
JDBCドライバーは/lib配下に配置しないとダメらしく、初期配置から移動させた。

mv /usr/share/java/mysql-connector-java.jar /opt/tomcat/lib/

tomcat5.5.PNG
JSPについては初心者でggりまくった結果、JSPも配置が重要らしく、
/opt/tomcat/webapps配下にjspディレクトリを作成し、パーミッションを750にし、所有者はtomcatに変更した。

cd /opt/tomcat/webapps
mkdir jsp
chown tomcat:tomcat jsp
chmod 750 jsp

tomcat6.PNG

/opt/tomcat/webapps/jsp配下には、test.jspを作成したが、
JSPの知識がなさすぎて、以下URLを参考にさせていただいた。
https://michael-e29.hatenadiary.org/entry/20111107/1320630444

jdbc:mysql://172.16.3.6:3306/world
↑DBサーバのアドレス:ポート番号/データベース名
※worldはデータベース名。
※ID,Name,CountryCode,District,Populationはデータベースのカラム名

###test.jspの中身###
<%@ page contentType="text/html; charset=utf-8" import="java.sql.*" %>

<html>
<head>
<title>DB参照テスト</title>
</head>

<body>
<h1>DB参照テスト</h1>

<tr>
<td>ID</td> <td>Name</td> <td>CountryCode</td> <td>District</td> <td>Population</td>
</tr>

<%
    Class.forName("com.mysql.jdbc.Driver");
    Connection conn=DriverManager.getConnection("jdbc:mysql://172.16.3.6:3306/world?" +
        "user=root&password=MySQL@001&useUnicode=true&characterEncoding=utf-8");
    Statement st=conn.createStatement();
    ResultSet res = st.executeQuery("select * from city;");

    while(res.next()){
        out.println("<tr>");
        out.println("<td>" + res.getString("ID") + "</td>");
        out.println("<td>" + res.getString("Name") + "</td>");
        out.println("<td>" + res.getString("CountryCode") + "</td>");
        out.println("<td>" + res.getString("District") + "</td>");
        out.println("<td>" + res.getString("Population") + "</td>");
        out.println("</tr>");
    }
    st.close();
    conn.close();

%>
</table>
</body>
</html>

APサーバとDBサーバの連携の準備ができたので、APサーバのTomcatサービスを再起動。
あとDBサーバのmysqldサービスを再起動し、ブラウザにJSPのパスを入力する。
ちなみにJSPファイルを置いたパスは /opt/tomcat/webapps/jsp/test.jsp だが、
ブラウザでは/webapps/配下を入力する。
http://WEBサーバのパブリックアドレス/jsp/test.jsp
DB参照.PNG

ぐちゃぐちゃだけど、一応DB参照できたので
一応WEB3層構成はできた・・・。
めちゃ時間かかったけど、つまづきながらハマりながら色々覚えれたので良かったです。
次回はNATゲートウェイの作成と、AnsibleでJSP内の文字列を置換することで
参照するDBを切り替えようと思います。

つづく

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java.net.http.HttpClient でJSONレスポンスを受信するとスレッドがフリーズした

事象に遭遇したのは AdoptOpenJDK jdk-11.0.9.1+1。

事象発生コード

数年ぶりにJavaで開発を行うことになり、外部APIをHTTPリクエストで呼び出してレスポンスのJSONを受信する必要が出てきた。

最後にJavaで開発した時はJDK 8でHTTPリクエストを行う標準ライブラリは
java.net.HttpURLConnectionくらいしかなかったが、
JDK 11からはjava.net.http.HttpClientが正式に標準ライブラリ入りしていたらしいので使用することにした。

JSONからのデシリアライズはJacksonを使おうと考えたが、HttpClientはレスポンスボディをreactive-streamsで処理しているらしい。

最も簡単な取り扱い方だとHttpResponse.BodyHandlers#ofString()で一度レスポンスボディをStringにしてからパースする方法だが、
せっかくのreactive-streamsなのでいい感じにデータ受信完了後にJSONを処理できる方法が無いか調べると
java.net.http.HttpResponse.BodySubscribers#mapping​(HttpResponse.BodySubscriber<T>, Function<? super T,​? extends U>)のjavadocが見つかった。

javadocの中でJacksonを利用してレスポンスボディを直接デシリアライズしてJavaオブジェクトを返すサンプルコードが書かれていたので、
そこで紹介されているコードをほぼそのまま流用させてもらうことにした。

実装は大体以下のようなコードになった。

public static <T> BodySubscriber<T> jsonSubscriber(
    ObjectMapper objectMapper,
    Class<T> klazz) {

    Objects.requireNonNull(objectMapper);
    Objects.requireNonNull(klazz);

    return BodySubscribers.mapping(
          BodySubscribers.ofInputStream(),
          (InputStream bodyStream) -> {
              try (bodyStream) {
                  return objectMapper.readValue(bodyStream, klazz);
              } catch (IOException e) {
                  throw new UncheckedIOException(e);
              }
          });
}

上記のメソッドで生成したサブスクライバを
java.net.http.HttpResponse.BodyHandler<T>の実装クラスで返すことで
HttpClientでレスポンスを受信した時にデシリアライズが実施されるようにしていた。

public class FooResponseHandler implements HttpResponse.BodyHandler<Foo> {

    private final HttpResponse.BodySubscriber<Foo> subscriber;

    public FooResponseHandler(ObjectMapper objectMapper) {
        this.subscriber = jsonSubscriber(objectMapper, Foo.class);
    }

    @Override
    public HttpResponse.BodySubscriber<Foo> apply(HttpResponse.ResponseInfo responseInfo) {
        if (responseInfo.statusCode() == 200) {
            return this.subscriber;
        }

        throw new RuntimeException("Unknown response");
    }
}

発生した問題

HttpClientの動作確認のために外部APIを呼び出しすると、なぜか数十秒経過後にタイムアウトが発生する。

TCPダンプを見るとAPIからのレスポンスは1秒かからず返ってきており、レスポンスボディも想定された内容だった。

しかし、HttpClientはタイムアウトが発生する。

デバッガーで原因個所を特定していくと、BodySubscribers.mapping()の第2引数に渡された
マッピング関数が実行された後でスレッドがフリーズしているらしいことが分かった。

このあたりでJDKの不具合を疑い調べてみるとStack Overflowなどに情報をまとめてくれている方たちがいた。

HttpClientは内部でI/O操作のためのExecutorCompletableFutureを実行しているが、
HTTPレスポンスボディを処理する中でブロッキングAPIが呼び出しされるとExecutorのスレッドが枯渇してしまうことがあるらしい。

具体的にどこでスレッドが枯渇しているのかは追いかけていないが、InputStreamからの読み取りでフリーズしているように見えたので、
レスポンスボディのバイト列をInputStreamに追加する処理と
InputStreamから読み取ってJSONデシリアライズする処理で競合のような状態が発生したと予想している。

対処方法は、紹介されているとおりBodySubscriber<T>BodySubscriber<Supplier<T>>に変更するしかないと思われる。

HttpClient内部処理が完了した後でレスポンスボディにアクセスする様になるため、スレッドの問題が回避できる。

ただ、この方法だとHTTPレスポンスボディのデータが全てInputStreamにバッファリングされていそうなので、
JSONデシリアライズみたいな目的の時はHttpResponse.BodyHandlers#ofString()を使用するのとメモリ効率などがあまり変わらない気がするのが気になる。

この不具合はJDK 13で修正されているようだが、同時にjavadocも更新されており
BodySubscriberないぶでレスポンスボディのInputStreamなどにアクセスする場合は
BodySubscriber<Supplier<T>>を使用する方法が推奨されるようになったようだ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java.net.http.HttpClient でHTTPレスポンスを受信するとリクエストがタイムアウトした

事象に遭遇したのは AdoptOpenJDK jdk-11.0.9.1+1。

事象発生コード

数年ぶりにJavaで開発を行うことになり、外部APIをHTTPリクエストで呼び出してレスポンスのJSONを受信する必要が出てきた。

最後にJavaで開発した時はJDK 8でHTTPリクエストを行う標準ライブラリは
java.net.HttpURLConnectionくらいしかなかったが、
JDK 11からはjava.net.http.HttpClientが正式に標準ライブラリ入りしていたらしいので使用することにした。

JSONからのデシリアライズはJacksonを使おうと考えたが、HttpClientはレスポンスボディをreactive-streamsで処理しているらしい。

最も簡単な取り扱い方だとHttpResponse.BodyHandlers#ofString()で一度レスポンスボディをStringにしてからパースする方法だが、
せっかくのreactive-streamsなのでいい感じにデータ受信完了後にJSONを処理できる方法が無いか調べると
java.net.http.HttpResponse.BodySubscribers#mapping​(HttpResponse.BodySubscriber<T>, Function<? super T,​? extends U>)のjavadocが見つかった。

javadocの中でJacksonを利用してレスポンスボディを直接デシリアライズしてJavaオブジェクトを返すサンプルコードが書かれていたので、
そこで紹介されているコードをほぼそのまま流用させてもらうことにした。

実装は大体以下のようなコードになった。

public static <T> BodySubscriber<T> jsonSubscriber(
    ObjectMapper objectMapper,
    Class<T> klazz) {

    Objects.requireNonNull(objectMapper);
    Objects.requireNonNull(klazz);

    return BodySubscribers.mapping(
          BodySubscribers.ofInputStream(),
          (InputStream bodyStream) -> {
              try (bodyStream) {
                  return objectMapper.readValue(bodyStream, klazz);
              } catch (IOException e) {
                  throw new UncheckedIOException(e);
              }
          });
}

上記のメソッドで生成したサブスクライバを
java.net.http.HttpResponse.BodyHandler<T>の実装クラスで返すことで
HttpClientでレスポンスを受信した時にデシリアライズが実施されるようにしていた。

public class FooResponseHandler implements HttpResponse.BodyHandler<Foo> {

    private final HttpResponse.BodySubscriber<Foo> subscriber;

    public FooResponseHandler(ObjectMapper objectMapper) {
        this.subscriber = jsonSubscriber(objectMapper, Foo.class);
    }

    @Override
    public HttpResponse.BodySubscriber<Foo> apply(HttpResponse.ResponseInfo responseInfo) {
        if (responseInfo.statusCode() == 200) {
            return this.subscriber;
        }

        throw new RuntimeException("Unknown response");
    }
}

発生した問題

HttpClientの動作確認のために外部APIを呼び出しすると、なぜか数十秒経過後にタイムアウトが発生する。

TCPダンプを見るとAPIからのレスポンスは1秒かからず返ってきており、レスポンスボディも想定された内容だった。

しかし、HttpClientはタイムアウトが発生する。

デバッガーで原因個所を特定していくと、BodySubscribers.mapping()の第2引数に渡された
マッピング関数が実行された後でスレッドがフリーズしているらしいことが分かった。

スレッドはフリーズしていたが、HTTPリクエストタイムアウトを発生させるスレッドは動いていたようで、
そのスレッドから例外が通知されるまでの数十秒間が待ち時間になっていたようだ。

原因と対処

このあたりでJDKの不具合を疑い調べてみるとStack Overflowなどに情報をまとめてくれている方たちがいた。

HttpClientは内部でI/O操作のためのExecutorCompletableFutureを実行しているが、
HTTPレスポンスボディを処理する中でブロッキングAPIが呼び出しされるとExecutorのスレッドが枯渇してしまうことがあるらしい。

具体的にどこでスレッドが枯渇しているのかは追いかけていないが、InputStreamからの読み取りでフリーズしているように見えたので、
レスポンスボディのバイト列をInputStreamに追加する処理と
InputStreamから読み取ってJSONデシリアライズする処理で競合のような状態が発生したと予想している。

対処方法は、紹介されているとおりBodySubscriber<T>BodySubscriber<Supplier<T>>に変更するしかないと思われる。

HttpClient内部処理が完了した後でレスポンスボディにアクセスする様になるため、スレッドの問題が回避できる。

ただ、この方法だとHTTPレスポンスボディのデータが全てInputStreamにバッファリングされていそうなので、
JSONデシリアライズみたいな目的の時はHttpResponse.BodyHandlers#ofString()を使用するのとメモリ効率などがあまり変わらない気がするのが気になる。

この不具合はJDK 13で修正されているようだが、同時にjavadocも更新されており
BodySubscriberないぶでレスポンスボディのInputStreamなどにアクセスする場合は
BodySubscriber<Supplier<T>>を使用する方法が推奨されるようになったようだ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JSP/サーブレット】 サーブレットクラスを使ってブラウザに「Hello World」を表示させてみた!

1,環境設定:pencil2:

Eclipse2020 Full Edition
Java11
Tomcat9

2,動的プロジェクト作成::blue_book:

3,サーブレットクラスの作成場所:card_box:

4、ディレクトリ構造とソースコード:notepad_spiral:

5、ブラウザをGoogle Chromeに設定:beginner:

6、サーバーの起動とブラウザ表示:tada:

サーバー起動(Tomcat)

ブラウザ表示(Google Chrome)

表示することができました!!

URLとリクエストメソッドにも注目すると、
 URL ⇨ localhot:8080/JSP_Servlet/HelloServlet
 Request Method : GET
となっています.

7、次のステップ:airplane:

次回は、JSPファイルからブラウザ表示をさせてみたいと思います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java JSP/サーブレット サーブレットクラスを使ってブラウザに「Hello World」を表示させてみた!

1,環境設定:pencil2:

Eclipse2020 Full Edition
Java11
Tomcat9

2,動的プロジェクト作成::blue_book:

3,サーブレットクラスの作成場所:card_box:

4、ディレクトリ構造とソースコード:notepad_spiral:

4、ブラウザをGoogle Chromeに設定:beginner:

5、サーバーの起動とブラウザ表示:tada:

サーバー起動(Tomcat)

ブラウザ表示(Google Chrome)

表示することができました!!

URLとリクエストメソッドにも注目すると、
 URL ⇨ localhot:8080/JSP_Servlet/HelloServlet
 Request Method : GET
となっています.

6、次のステップ:airplane:

次回は、JSPからブラウザ表示をさせてみたいと思います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】AtcorderのABC-189に参加しました。

こんばんは。

2021/1/23に、AtcorderのABC-189に参加しました。
レートは以下の通りとなっています。

image.png

https://atcoder.jp/users/ishikawaryou

C問題は処理時間でエラーになり、良いロジックを思いつけず負けました・・。
まだまだですね。
ともあれレートを13→51に更新!
A問題は5分以内、B問題15分以内で安定して解けるようになってきました。
半年前に始めたときはA問題ですら会社の昼休み中(1時間-お弁当の時間)に解けなかった事を思うと、着実な進歩です。

A問題

入力した3文字が全部同じか、そうでないかチェックするというもの。
String型で入力した文字列を、char型にして同じかチェックしました。

import java.util.Scanner;
import java.util.HashSet;
import java.util.Set;

public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
  String c = sc.next();
  if((c.charAt(0)==c.charAt(1))&&(c.charAt(1)==c.charAt(2))){
System.out.println("Won");  
  }else{
System.out.println("Lost");  

  }
}
}

B問題

飲んだアルコール飲料の容量(v)と、アルコール度数(p)から、摂取したアルコール量(al)を求め、アルコール許容量(x)を超えて酔っぱらうかどうかを調べます。

整数型での答えを求められていましたが、int型は小数点以下を切り捨ててしまうので、思い切って数字を100倍して、アルコール度数10.5%→1050と算出させるようにしました。
もっとスマートなやり方があると思うんですけどね・・。

import java.util.Scanner;
import java.util.HashSet;
import java.util.Set;

public class Main{
public static void main(String args[]){
  Scanner sc = new Scanner(System.in);
  int n = sc.nextInt();
  int x = sc.nextInt();
  int v[] = new int[n];
  int p[] = new int[n];
  int al = 1;
  char flg = '0';
  for(int i=0;i<n;i++){
    v[i] = sc.nextInt();
    p[i] = sc.nextInt();
    if(i==0){
    al = v[i]*p[i]; 
    }
    else
    {
    al = al+(v[i]*p[i]); 
    }
    if(al>x*100){
      System.out.println(i+1);
      flg = '1';
      i=n;
    }
      //System.out.println("al/100 " + al/100);
  }

  if(flg=='0'){
      System.out.println(-1);
  }

}
}

C問題

*不正解のためソースは割愛します。
ロジック自体は正解に近づいていたようですが、処理時間がかかりTLEとなりました。
(21ケースAC、12ケースでTLE)。

やはり2重ループはだめでしたね。

感想

週末にちょっとした(失礼?)戦いがあるのは、いい刺激になります。
僕はこれでも高校時代は数学が好きで得意科目だったので、少し高校時代の数学の楽しさを思い出してきて楽しいです。これなら継続できそうな気がします。

これからもコツコツ取り組んで、茶色を目指したいと思います!
同じく灰色レベルで頑張っている方、お互い頑張りましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む