キャッシュとセッションとクッキーについて簡単に

クッキー

  • 「誰が」というユーザー情報をブラウザに保存
  • 一時的なものと永続的なものが存在
    • 無効にできる

セッション

  • ユーザーの「行動」をブラウザもしくはサーバーに保存
  • クッキーと違い永続的なものは存在しない(ブラウザを閉じるか、サイトから離れると削除される)
    • 無効にできない

キャッシュ(ブラウザのキャッシュ)

  • 画像やファイルが保存され、サイトへのアクセス速度向上
  • キャッシュファイルが保存されるフォルダがローカルに存在
  • 永続的(有効期限を設定可能)

Java + Thymeleafでth:eachの繰り返し表示を整理

問題

コントローラーからのデータをテーブル表示で並べてくれとの要件
問題は一部がList型なため、そのサイズ分の行数必要になり、
その他のデータは中身が同じなため、同じデータが繰り返し表示されてなんか嫌だった

やったこと

そこで、前回も大変お世話になった#numbers.sequenceを使って解決
繰り返し表示する必要のない列は最初の行だけ表示するよう、
th:if="${i == 0}"で制御して、th:rowspan="${list.size()}"で結合
これで繰り返し表示が必要なものだけ、サイズ分行数が表示され、
それ以外は、大きな一行でまとまったテーブルの完成

<table>
  <thead>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
    </tr>
  </thead>
  <tbody>
    <tr th:each="i : ${#numbers.sequence(0, sampleForm.sampleList.size()-1)}">
      <td th:if="${i == 0}" th:rowspan="${sampleForm.sampleList.size()}" th:text="1"></td>
      <td th:if="${i == 0}" th:rowspan="${sampleForm.sampleList.size()}" th:text="2"></td>
      <td th:text="${sampleForm.sampleList[i]}"></td>
    </tr>
  </tbody>
</table>

SpringBoot + Thymeleafでチェックボックスを任意の列で表示

環境

Spring Boot 2.7.11
Java 11

目的

コントローラーから取得したリストを基に任意の列で、チェックボックスを横並びにしたい

実装コード

<div class="form-group row">
    <details>
        <summary>LIST1</summary>
        <table style="margin-left: 60px; width: 90vw">
            <tr th:each="i : ${#numbers.sequence(0, list1.size() - 1, 3)}">
                <td th:each="value, status : ${list1.subList(i, i + 3 < list1.size() ? i + 3 : list1.size())}" 
                th:style="${list1.size()} >= 3 ? 'width: 30vw;' : (${status.index} % 3 == 0 ? 'width: 15vw;' : 'width: 30vw;')">
                    <input class="form-check-input" type="checkbox" th:value="${value}">
                    <label class="form-check-label" th:text="${value}"></label>
                </td>
            </tr>
        </table>
    </details>
</div>
<div class="form-group row">
    <details>
        <summary>LIST2</summary>
        <table style="margin-left: 60px; width: 90vw">
            <tr th:each="i : ${#numbers.sequence(0, list2.size() - 1, 3)}">
                <td th:each="value, status : ${list2.subList(i, i + 3 < list2.size() ? i + 3 : list2.size())}" 
                th:style="${list2.size()} > 2 ? 'width: 30vw;' : (${status.index} == 0 ? 'width: 15vw;' : 'width: 30vw;')">
                    <input class="form-check-input" type="checkbox" th:value="${value}">
                    <label class="form-check-label" th:text="${value}"></label>
                </td>
            </tr>
        </table>
    </details>
</div>

表示画面

説明

上記コードは3列で表示するもの
trタグのeachはコントローラーから受け取ったlist1というリストを3つずつ扱うために、
i : #numbers.sequence(from, to, step)1のstepを3と指定
Javaでいうfor (int i = 0; i < list1.size() - 1; i+=3)と同じ

tdタグのeachJavaの標準メソッドsubList(form, to)2でlist1を、
素数が3つずつになるようi+3までeach文を実行する

th:styleの三項演算子は、チェックボックス各々の幅をウィンドウのサイズに応じて、
単純にwidth: 30vw;で3分割できればよかったのだが、
リストのサイズが2の時だけ1つ目と2つ目のチェックボックスの間が広くなり、
他のグループの項目と2つ目のチェックボックスの位置がずれてしまうため、
一番最初の要素の幅だけ1/6のサイズに指定した
・リストサイズが1の時、幅によって少々ズレることがあったためth:styleの最初の条件を2未満に

注意

時間がなかったために、このような可読性の低いコードをVIEWに書くことになってしまい、
探せばもっと単純で簡単な実装方法があると思います。


  1. Thymeleafのユーティリティメソッド:Tutorial: Using Thymeleaf (ja)
  2. Java11ドキュメント:List (Java SE 11 & JDK 11 )

AOJ ALDS1_3_C 双方向連結リスト (Java11)

最終的な提出コード(AC)

class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Deque<Integer> list = new ArrayDeque<Integer>();
         String str = br.readLine();
        int n = Integer.parseInt(str);

        for (int i = 0; i < n; i++) {
            String tmp = br.readLine();
            if (tmp.equals("deleteFirst")) {
                list.pop();
            } else if (tmp.equals("deleteLast")) {
                list.removeLast();
            } else {
                String command = tmp.substring(0, tmp.indexOf(" "));
                int x = Integer.parseInt(tmp.substring(tmp.indexOf(" ")+1));
                if (command.equals("insert")) list.push(x);
                else if (command.equals("delete")) list.remove((Integer) x);
            }
        }
        Iterator iterator = list.iterator();
        int i = list.size();
        int j = 0;
        while (iterator.hasNext()) {
            if (j != i-1) {
                System.out.print(iterator.next());
                System.out.print(" ");
            } else {
                System.out.println(iterator.next());
            }
            j++;
        }
    }
}

自力で届いた回答

class Main {
    public static void main(String[] args)  throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        var list = new ArrayList<Integer>();
        String str = br.readLine();
        int n = Integer.parseInt(str);
        
        for (int i = 0; i < n; i++) {
            String tmp = br.readLine();
            if (tmp.equals("deleteFirst")) {
                list.remove(0);
            } else if (tmp.equals("deleteLast")) {
                list.remove(list.size()-1);
            } else {
                String command = tmp.substring(0, tmp.indexOf(" "));
                int x = Integer.parseInt(tmp.substring(tmp.indexOf(" ")+1));
                if (command.equals("insert")) list.add(0, x);
                else if (command.equals("delete")) list.remove((Integer) x);
            }
        }
        for (int i = 0; i < list.size(); i++) {
            if (i != list.size()-1) {
                System.out.print(list.get(i));
                System.out.print(" ");
            } else {
                System.out.println(list.get(i));
            }
        }
    }
}
  • テストケース10でTLEになり通らず

元々は入力をScannerで受け取っていたが、
sc.next()
だと、空白を区切りと判断し文中の x を受け取れておらず
sc.nextLine()
で、一行受け取ってしまえば良かったと思った頃には後者のコードを記述済み


前者と後者で違いは、

  • x をArrayDeque<>かArrayList<>に入れるか

  • 使用するデータ構造に伴った関数の利用

テストケース10はおそらく、全てのcommandがinsertであり、
ArrayDequeのpush(),addFirst()とArrayListのadd()に計算量の差があるとみる

  • SE11のソースを読んでみたが、イマイチ理解に至らず

SQLローダー実行時、マッピング対象外の日付をテーブル(一列目)へ登録

目的SQLローダーでCSVを取り込む際に、マッピング対象ではない日付をテーブルへ追加したい

ctlファイル(色々省略)

・
・
FIELDS TERMINSTED BY '.'
TRATLING NULLCOLS
(
    INPUT_DATE CAHR "TO_CHAR(SYSDATE, YYYY/MM/DD)", 
    COL1,
    COL2,
    COL3,
)

CSV( input )

CO1 COL2 COL3
sample1 sample2 sample3


上記のctlファイルでSQLローダーを実行したら、テーブルの値が下記の通り一列ずれました。

テーブル

INPUT_DATE COL1 COL2 COL3
2023/01/01 sample2 sample3


解決マッピングに関係のない項目は、マッピング対象の後に定義し直すことにより解決しました。

ctlファイル(after)

・
・
FIELDS TERMINSTED BY '.'
TRATLING NULLCOLS
(
    COL1,
    COL2,
    COL3,
    INPUT_DATE CAHR "TO_CHAR(SYSDATE, YYYY/MM/DD)", 
)

テーブル(after)

INPUT_DATE COL1 COL2 COL3
2023/01/01 sample1 sample2 sample3

ABC249 C - Just K

atcoder.jp

キーワード

  • ビット全探索

  • ビット演算

  • シフト演算


キーワードについて解説していきます

シフト演算

見やすさ重視でバイナリ表記で出力していますが、下記コードは右シフトの演算です
例:0010 >> 0001 = 00001, 1000 >> 0010 = 0010
演算子の右側にある1が見えなくなるまでずらしていき、
同じ分だけ、左側もずらされる

for i in range(1,4):
    for j in range(3):
        print(bin(i>>j))
>>>
0b1 # 0b1 >> 0b0
0b0 # 0b1 >> 0b1
0b0 # 0b1 >> 0b10
0b10 # 0b10 >> 0b0
0b1 # 0b10 >> 0b1
0b0 # 0b10 >> 0b10
0b11 # 0b11 >> 0b0
0b1 # 0b11 >> 0b1
0b0 # 0b11 >> 0b10


ビット演算 ( &のみ )

&演算子は、お互い1の時のみ1を返します
例:0001 & 0001 = 0001, 1010 & 1010 = 1010, 0101 & 1001 = 0001
※ and(論理演算子)で&(ビット演算子)となり別物

print(bin(7&3)) # 0b111 & 0b11
>>>
0b11


ビット全探索

3つのうち、2パターンの合計は2^3(1<<3) = 8通り
2パターンとはバイナリの0と1、つまり選ぶ( 1 )か選ばない( 0 )か
これを使って、N個の文字列から好きな個数を選択するための全通りが行える

for i in range(1<<3):
    for j in range(3):
        print(bin(i>>j & 1))
>>>
0b0
0b0
0b0

0b1
0b0
0b0

0b0
0b1
0b0

0b1
0b1
0b0

0b0
0b0
0b1

0b1
0b0
0b1

0b0
0b1
0b1

0b1
0b1
0b1


解答

キーワードに関する説明は省くとして、
アルファベットの配列(a = 0 を起点とする,)に、選択した文字列に含まれる単語をカウントしていく
配列の要素つまりカウント数が==Kとなっている数が一番多い時をansに記憶しておく

N, K = map(int, input().split())
S = [input() for _ in range(N)]
ans = 0

for i in range(1<<N):
    alph = [0]*26
    cnt = 0
    for j in range(N):
        if i>>j & 1:
            for k in S[j]:
                alph[ord(k)-ord('a')] += 1
                
    for j in range(26):
        if alph[j] == K:
            cnt += 1
            ans = max(ans, cnt)

print(ans)



参考
bit 全探索 - けんちょんの競プロ精進記録
ビット演算 (bit 演算) の使い方を総特集! 〜 マスクビットから bit DP まで 〜 - Qiita

ABC243 C - Collision 2

atcoder.jp

愚直に解こうとすると時間内に処理を終えることができずTLEになるので、
Yをキーとした、
Lの中で一番Xが大きいもの(left_max)、Rの中で一番Xが小さいもの(right_min)のみで、
解けば実行時間の制限にひっかかることなく処理を終えれます

あとは、どんな時にYesとなるか条件を書けば無事ACです
and 以降を忘れると、
X = 1, 2, 3, 4 Y = 1, 1, 1, 1 S = LLRR
こんな時にもYesを出力しちゃうので、忘れないように

解答

N = int(input())
X,Y = [],[]
for _ in range(N):
    x,y = map(int,input().split())
    X.append(x)
    Y.append(y)
S = input()

left_max, right_min = dict(),dict()
for i in range(N):
    if S[i] == 'R':
        if Y[i] in right_min:
            right_min[Y[i]] = min(X[i], right_min[Y[i]])
        else:
            right_min[Y[i]] = X[i]
    else:
        if Y[i] in left_max:
            left_max[Y[i]] = max(X[i], left_max[Y[i]])
        else:
            left_max[Y[i]] = X[i]

    if S[i] == 'R':
        if Y[i] in left_max and right_min[Y[i]] < left_max[Y[i]]:
            print('Yes')
            exit()
    else:
        if Y[i] in right_min and right_min[Y[i]] < left_max[Y[i]]:
            print('Yes')
            exit()

print('No')