AtCoder Beginner Contest 119・125・132・134 A~C問題

前書き

AtCoder Beginner Contest 119・125・132・134 A~C問題を解きました。

A問題(ABC119)

  • 難易度:灰
  • 時間:2分

atcoder.jp

Y,M,D=map(str,input().split('/'))
S=int(Y+M+D)
if S<=20190430: print('Heisei')
else: print('TBD')

B問題(ABC119)

  • 難易度:灰
  • 時間:5分

atcoder.jp

N=int(input())
_sum=0
for i in range(N):
  x,u=map(str,input().split())
  if u=='JPY': _sum+=float(x)
  elif u=='BTC': _sum+=float(x)*380000.0
print(_sum)

A問題(ABC125)

  • 難易度:灰
  • 時間:2分

atcoder.jp

A,B,T=map(int,input().split())
print((T//A)*B)

B問題(ABC125)

  • 難易度:灰
  • 時間:3分

atcoder.jp

V[i]-C[i]>0となる時の差分(V[i]-C[i])を合計すれば、
X - Yの最大値を獲得できます。

N=int(input())
V=list(map(int,input().split()))
C=list(map(int,input().split()))
count=0
for i in range(N):
  if V[i]-C[i]>0:
    count+=V[i]-C[i]
print(count)

A問題(ABC132)

  • 難易度:灰
  • 時間:7分(1WA)

atcoder.jp

アルファベットが2回"丁度"でなく2回"以上"を勘違いしてWAを出してしまいました。

import collections,sys
S=list(input())
c = collections.Counter(S)
for i in c.values():
  if i!=2:
    print('No')
    sys.exit()
print('Yes')

B問題(ABC132)

  • 難易度:灰
  • 時間:6分

atcoder.jp

i-1 , i , i+1番目で構成された配列の中央値を取得して、
配列pのi番目と一致すればカウントするというアルゴリズムを書きます。

import statistics
n=int(input())
p=list(map(int,input().split()))
count=0
for i in range(1,n-1):
  if p[i]==statistics.median(p[i-1:i+2]):
    count+=1
print(count)

C問題(ABC132)

  • 難易度:灰
  • 時間:6分

atcoder.jp

入力値をソートして、(N/2-1)番目と(N/2)番目要素の差がそのまま閾値Kのパターンになります。

N=int(input())
d=list(map(int,input().split()))
d.sort()
print(d[int(N/2)]-d[int(N/2)-1])

A問題(ABC134)

  • 難易度:灰
  • 時間:30秒

atcoder.jp

a=int(input())
print(3*a**2)

B問題(ABC134)

  • 難易度:灰
  • 時間:3分

atcoder.jp

import math
N,D=map(int,input().split())
print(math.ceil(N/(D*2+1)))

C問題(ABC134)

  • 難易度:灰
  • 時間:7分

atcoder.jp

入力数値の中で最大値と2番目に大きな値(最大値と同値でもOK)を保存します。
j番目の入力が最大値と等しい場合、2番目に大きな値を出力します。

最大値が複数ある場合、2番目に大きな値=最大値なので、問題ありません。

N=int(input())
_max,_secmax=0,0
A=[int(input())for i in range(N)]

for a in A:
  if a>=_max:
    _secmax=_max
    _max=a
  elif a>=_secmax:
    _secmax=a
    
for j in range(N):
  if A[j]==_max: print(_secmax)
  else: print(_max)

データベース設計をやってみた

前書き

前回はこんな感じでUI設計・機能設計を簡単にやっていきました。
melheaven.hatenadiary.jp

今回はデータ設計に取り掛かろうと思います。

データ設計

データ設計では、以下の3つを決定する必要があるみたいです。

  • データの具体的な中身
  • データベース設計
  • データの流れ

上記に倣って、データ設計に取り組んでいこうと思います。
qiita.com

データの具体的な中身

以下の4種類に大別できることは明白です。

  • Webのフォームに打ち込むデータ
  • データベースから取得するデータ
  • Web画面に表示するデータ
  • データベースに格納するデータ

では大まかに必要なデータとは何か・・・。

【ユーザー情報】
  • ユーザーID(一意)
  • ユーザー名前
  • パスワード(Twitter or Google認証を適用したいので不要かも)
  • TwitterID
  • GithubID
  • GoogleID
  • ブログURL

今回は1ユーザーにつきページは1つです。よって1対1の関係性です。
でもユーザーIDとページIDは1対1の関係ですが、別にしておいた方が良いかと考えました。
理由は「将来的に1ユーザーにつき複数のページを持つシステムにしたい時に楽だと思った」からです。

あとログイン認証はGoogle or Twitter認証で実装しようと思います。そちらの方が便利でしょう?

【ページ情報】
  • ページID(一意)
  • 管理ユーザー(ID)
  • 現時点で保存されている記事内容(HTML?)
  • 公開 or 非公開?
  • 更新日時

イマイチ理解しきれていないのは、記事内容をどういう形でDBに保存すれば良いのかです。
理想としては、QiitaやブログのようなHTML・画像・リンクを繋げて一つのWebページにしてくれる機能です。調査しているとCMSがヒットしてきました。次の詳細設計にてこの点は追求しようと思います。

【タグ情報】
  • タグID
  • タグ名前
【タグとページを結びつける情報】
  • タグ=ページID
  • タグID
  • ページID

タグ検索する時に1回のクエリで全てのページを獲得したい!となった場合に便利なテーブルです。
タグ=ページに一意IDを設定させました。

【いいね!情報】
  • いいね!ID
  • いいね!するユーザーID
  • いいね!されるページID

同様に「いいね!」情報を結びつけるテーブルも準備します。
ひとまずはこんなところでしょうか。

データベース設計

ER図で表現してみました。

f:id:electric-city:20210414150639p:plain
ER図

使用アプリはLucid Chartです。
www.lucidchart.com

データの流れ

上記の変更点やデータベース設計から以下のデータフローを作成できました。

f:id:electric-city:20210414153032p:plain
UI設計+機能設計+データ設計

ひとまずこんなところでデータベース設計を完了しようと思います。

次回

次回以降は詳細設計に着手しようと思います。

UI設計・機能設計をやってみる

前書き

前回、こんな感じで要件定義をしました。
今回はUI設計・機能設計(処理内容・データ・操作)をやっていきます。
melheaven.hatenadiary.jp

UI設計

必要最低限の画面は以下の3つ。加えてログイン画面・マイページ(パスワード変更など)とかですかね。

  • 社員・学生メイン画面
  • 個人ページ画面
  • 個人ページ編集画面(Qiitaっぽく)
f:id:electric-city:20210412112415p:plain
最低限のUI

製作はFigmaを用いました。
www.figma.com

機能設計

1. 社員・学生メイン画面

機能名:「タグ別に登録個人ページを表示する」

【必要なデータ】
  • フォームで取得したい情報:タグ情報
  • タグ情報と個人記事のURL、タイトル
【処理内容】
  • 検索フォームからタグ情報を受け取る
  • DBにて検索結果に該当する上位20〜30件を取得
  • 続きの20〜30件を取得
【ユーザー入力】
  • 「続き」ボタンをクリック

2. 個人ページ画面

機能名:「個人のページを表示する」

【必要なデータ】
【処理内容】
  • DBからマークアップで記載されたHTMLを取得
  • 「いいね!」を押すとDBに格納される
  • DBに格納されたいいね数を非同期で取得
【ユーザー入力】
  • いいね!ボタンをクリック

3. 個人ページ編集画面

【必要なデータ】
  • 記事の編集過程(マークアップ言語で)
  • 記事の編集を非同期でプレビューにて表示
  • 公開 or 非公開の情報
  • ログイン情報
【ユーザー入力】
  • 記事の編集
  • マークアップでの記述をサポートする機能
  • 公開 or 非公開ボタンをクリック

4. タイトルバー

機能名:「重要ページへの遷移」

【処理内容】
  • アカウント作成ページに遷移
  • ログインページに遷移
  • マイページに遷移
【ユーザー入力】
  • アカウント作成ページをクリック
  • ログインページをクリック
  • マイページをクリック

5. マイページ

【処理内容】

機能名:「いいね!」したページの表示

  • 「いいね!」したページを上位10件を取得
  • 続きの10件を取
【必要なデータ】
  • ユーザーがいいね!した記事
  • ユーザー情報
【ユーザー入力】
  • 「いいね!」ページのクリック
  • マイページのパスワード変更のクリック

最終的なイメージ

f:id:electric-city:20210413173030p:plain
機能設計+UI設計

次回

次回はデータ設計をしていきます。
データの具体的中身・データベース設計・データフローを設計してER図に落とし込みます。

AtCoder Beginner Contest 198 A〜C問題

前書き

AtCoder Beginner Contest 198 A〜C問題を解きました。

A問題

  • 難易度:灰
  • 時間:1分

atcoder.jp

N=int(input())
print(N-1)

B問題

  • 難易度:灰
  • 時間:10分

atcoder.jp

回文問題です。0を一個ずつ増やしながら回文チェックしていきました。

import sys
N=input()
def check(string):
 return string.find(string[::-1])

for i in range(10):
  S=check(i*'0'+N)
  if S==0:
    print('Yes')
    sys.exit()
  #print(i*'0'+N,S)
print('No')

C問題

  • 難易度:茶
  • 時間:40分

atcoder.jp


正直簡単なC問題でしたが、WA×3に長時間苦しめられました...。
結局、"R>=_R" → "R>_R"にすれば良かっただけ・・・。

一足で進める距離(R)>ユークリッド距離(_R)の時は2歩です。

一足で進める距離(R)<=ユークリッド距離(_R)の時に以下の計算での歩数で移動可能です。
→ _R / R の切り上げ

import math,sys
R,X,Y=map(int,input().split())
_R=math.sqrt(X**2+Y**2)
if R>_R:
  print(2)
  sys.exit()
  
print(math.ceil(_R/R))