TIPS」カテゴリーアーカイブ

TIPS(Ruby:文字列と数値が混ざったものを1行でそれぞれの変数に入力値を受け取りたい)

目標:プログラミング問題でよくある文字列と数値が混ざったものを1行で入力値を受け取りたい

入力例

3
Tanaka 24
Sato 35
Suzuki 12

実践

#最初の3を変数に代入する

n = gets.to_i

#新たな変数に空の配列を多重代入する。
name,age = [],[]

#n回 (3回)  i == 0 のとき、つまり最初の文字列をnameに文字列として代入
#半角スペースを挟んだ数値をageに数値として代入する。
n.times.map { gets.split.map.with_index { |val, i| i == 0 ? name << val : age << val.to_i } }

#nameとageに期待していたように入っているか確認する。
p name, age

https://paiza.io/projects/4T8pWrwlF0UOH0goc0gopw

↑こちらにコピペして「実行」で確認できます。
↓このような出力結果になっていて、nameに文字列がageに数値が入っていることが確認できます。

TIPS(Ruby:1から1000の数字に任意の数字が何個含まれるか?)

目標:なにがしたいか?

1から1000の数字に任意の数字が含まれるのは何個あるか?

問題

1から1000の数字に任意の数字がいくつ含まれているか、調べたくなりました。
例えば13の数字が入るのは 13, 113, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 213, 313
413,513,613,713,813,913であるので、合計 20となります。

与えられる入力値

13

期待する出力

20

コードと解説

#1行目の入力値を受け取る
n = gets.chomp

#1~1000まで配列を作成して配列内の数字を全て文字列に変換する
days = [*1..1000].map(&:to_s)

#include?で任意の数字を選択して長さを出力する
puts days.select { |i| i.include?(n) }.size

https://paiza.io/ja/projects/new

↑こちらにコピペして「実行」で確認できます。

↓このような出力結果になっていればOKです。

TIPS(Ruby:特定の数字や1の位10の位の値で条件分岐する)

目標:なにがしたいか?

特定の数字や1の位10の位の値で条件分岐する方法

問題

あなたはマンションに引っ越しを考えています。
しかし、嫌な数字があり、その数字が含まれる部屋番号の入居を避けることにしました。
そこで、今空いている部屋のうち、部屋番号のどの桁にも嫌な数字が含まれていない部屋番号をリストアップして伝えることにしました。

条件

1:一の位に4が含まれる部屋番号 例:104,204,304
2:13が含まれる部屋番号 例:113,213,313
3:部屋番号666

・1行目に部屋の総数 n
・2行目以降に各部屋番号を表す整数 room_i (1 <= i <= m)

が改行区切りで与えられるので、希望するマンションの部屋番号をすべて改行区切りで出力して下さい。

入力される値

入力は以下のように与えられます。

n #部屋の総数
room_1 #1個目の部屋番号
room_2 #2個目の部屋番号
...
room_n #n個目の部屋番号

それぞれの値は文字列で標準入力から渡されます。

与えられる入力値

9
101
130 
304 
401 
501
666
704
813
902

期待する出力

101
130
401
501
902

コードと解説

#1行目の入力値を受け取る
n = gets.to_i

#n回繰り返す
n.times do |i|

#2行名以降の入力値を受け取りバラバラにする 例:["1", "0", "1"]
  numbers = gets.chomp.chars
#1の位が4の場合か666の場合に対応
  if numbers[-1] == "4" || numbers.join == "666"
#1の位が3で10の位が1の場合に対応して13があるかどうか対応する
  elsif numbers[-1] == "3" && numbers[-2] == "1"
# 上記の条件以外のとき部屋番号を出力する
  else puts numbers.join
  end
end

https://paiza.io/ja/projects/new

↑こちらにコピペして「実行」で確認できます。

↓このような出力結果になっていればOKです。

※ポイント

入力値が301のときgets.chomp.charsで[“1”, “0”, “1”]とひとつずつバラバラにすることができる。

今回は3桁の数字だったが4桁以上の場合を考えて、

配列の[-1]を使うことで1の位、[-2]で10の位で条件分岐してやることができる。

TIPS(Ruby:ポイントカード機能その2 特定の日のポイント数をn倍する)

ポイントカード機能その2

問題

とあるお肉屋さんではポイントカードが導入されていて、買い物をするたびに購入金額に応じたポイントがたまります。 加算されるポイントは次の 3 つのルールに従って決定されます。

1. 通常は購入金額の1%(小数点以下切り捨て)とする
2. 4のつく日は購入金額の4%(小数点以下切り捨て)とする
3. 29のつく日は購入金額の29%(小数点以下切り捨て)とする

最終的にポイントカードに何ポイントあるか出力してください。(小数点以下切り捨て)

入力値について

入力は以下のように与えられます。

N    #各買い物の数
day_1 plice_1 #1回目の買い物の日付 day_1 日, 購入金額 plice_1 円
day_2 plice_2 #2回めの買い物の日付 day_2 日, 購入金額 plice_2 円
day_N plice_N #N枚目のレシートの日付 day_N 日, 購入金額 plice_N 円
1行目には今月分の買い物の回数を表す整数 N が入力されます。
続く N 行には各買い物の情報が入力されます。

与えられる入力値

5
2 1000
14 2000
15 4000
24 3000
29 29000

期待する出力

8660

コードと解説

#1行目の入力値を受け取る
n = gets.to_i

#ポイントは最初は0なので0で初期化する
point = 0

#n回繰り返す
n.times do |i|
  #2行名以降の入力値を受け取る
  day,plice = gets.split.map(&:to_i)
  
  #4のつく日の処理を書く
  if day == 4 || day == 14 || day == 24 
     
  #4%なので先に計算してから.floorで小数点以下を切り捨てる
     point += (plice.to_f / 100) * 4.floor
  #29日の処理を書く
  elsif day == 29
  
  #29%なので先に計算してから.floorで小数点以下を切り捨てる
  point += (plice.to_f / 100) * 29.floor
  
  #普通の日は1%なので先に計算してから.floorで小数点以下を切り捨てる
  else point += (plice.to_f / 100).floor
  end
end
#ポイントを出力する
puts point.to_i

https://paiza.io/ja/projects/new

↑こちらにコピペして「実行」で確認できます。

↓このような出力結果になっていればOKです。

※ポイント

.floorで小数点以下を切り捨てることができる

TIPS(Ruby:文字列+数値を数値の昇順にソートする)

目標:なにがしたいか?

文字列+数値を数値の昇順にソートする

問題

とあるWebサービスのユーザー ID は「ユーザーネーム + シリアルナンバー」となります。
例えば、satouさんが1番目に登録した場合、ユーザー ID は「satou1」、
suzukiさんが 1081 番目に登録した場合、ユーザー ID は「suzuki1081」になります。
いま、この Webサービスに登録しているユーザーのうち N 人のユーザー ID が与えられるので、それらを番号の若い(小さい)順に並べて出力してください。

条件
・1 行目にユーザー ID の個数を表す整数 N が与えられます。(1 ≦ N ≦ 200)
・名前は全て英小文字のみからなります
・シリアルナンバーは全て 1 以上 100 以下の整数で、先頭に不要な 0 を含みません。
・シリアルナンバーはユニークなので同じ番号はないです。

与えられる入力値

5
satou1
suzuki1081
tanaka990
yamada100
kawase1001

期待する出力

satou1
yamada100
tanaka990
kawase1001
suzuki1081

コードと解説

#入力値(数値)を受け取る
n = gets.to_i

#空の配列を作成する
ary,answer = [],[]

#n回繰り返す
n.times do |i|
  #2行名以降の入力値を文字列として受け取る
  user_id = gets.chomp 

  #数字の手前で2つに分割する
  user_id = user_id.split(/(?=\d)/,2)
  
  #分割したものの数字が文字列のままなので数値に変換する
  user_id[1] = user_id[1].to_i
  
  #空の配列aryにuser_idを格納していく
  ary << user_id
end
#配列を数字の昇順に並び替える
ary = ary.sort_by{ |_, number| number }

#文字列と数字を繋げて1行ずつ出力
n.times { |i| puts ary[i].join }

https://paiza.io/ja/projects/new

↑こちらにコピペして「実行」で確認できます。

↓このような出力結果になっていればOKです。

※ ary = ary.sort_by{ |_, number| number }がポイント

[["satou", 1], ["suzuki", 1081], ["tanaka", 990], ["yamada", 100], ["kawase", 1001]]

配列の0番目の文字列で並び替えずに

配列の1番目の数値を基準にして昇順に並び替えている。

 

TIPS(Ruby:配列に任意の文字列が含まれているか?2)

目標:なにがしたいか?

配列の要素がすべてユニークな(同じ要素がない)ときの

ある配列の全要素の中に指定された配列の全要素がいくつ含まれているか?

問題

くじ引きゲームを作成しています。このゲームでは1 から50 までの好きな数字を 6 つ選びます。
抽選では同様に 6 つの当選番号が発表され、
購入したくじの数字と一致していた数字の数に応じて賞品が当たります。
N 枚くじを購入したときに、N 枚の宝くじそれぞれについて、
当選番号と一致した数字の数について調べるプログラムを書くことにしました。

与えられる入力値

22 2 10 24 35 25
3
36 7 10 24 34 42
26 2 42 12 35 38
35 11 40 47 45 49

期待する出力

2
2
1

コードと解説

#1行目の入力値を配列にして受け取る
lucky_number = gets.split.map(&:to_i)

#2行目の入力値を受け取る
n = gets.to_i

#N枚くじがあるのでN回繰り返す
n.times do |i|

  #半角スペース刻みの入力値を受け取る
  lottery = gets.split.map(&:to_i)

  #くじのあたり番号と購入したくじの重複した部分の長さを出力する
  puts (lucky_number & lottery).size
end

https://paiza.io/ja/projects/new
↑こちらにコピペして「実行」で確認できます。
↓このような出力結果になっていればOKです。

※配列と配列の重複している部分は積集合&を使うことで検出できる。

積集合

GitHubに芝を生やす方法

GitHubに結構コミットしているのに全然反映されていない時

git config user.email

gitコマンドに紐づいているアドレスを確認しよう。

GitHubのSettingsから左のサイドバーのEmailsで

登録しているメールアドレスがわかるので

git config user.email メールアドレス

で変更して↓のコマンドで反映されているか確認

git config user.email

GitHubで芝が生えていたらOK

destroy_allの使い方(1対他モデルの一括削除)

destroy_allとは?

すでにテーブルに存在するレコードを一括で削除するメソッドです。

テーブルの状態

usersテーブル(1)にtasksテーブル(多)がhas_manyで紐付いています。

user.rbはこのようになっています。

# == Schema Information
#
# Table name: users
#
#  id              :bigint           not null, primary key
#  admin           :boolean          default(FALSE)
#  email           :string(255)
#  image           :string(255)
#  name            :string(255)
#  password_digest :string(255)
#  remember_digest :string(255)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#
class User < ApplicationRecord
  has_many :tasks, dependent: :destroy
  accepts_nested_attributes_for :tasks, allow_destroy: true

1対多の場合は1の方(例としてuserとする)has_many :tasks, dependent: :destroyを追加記述することで、userを消したときに紐付いているtaskも削除されるようにできる!

sessions_helper.rbはこのようになっています(ほぼRailsチュートリアルと同じです)

module SessionsHelper

  # 記憶トークンcookieに対応するユーザーを返す
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  # 渡されたユーザーがログイン済みユーザーであればtrueを返す
  def current_user?(user)
    user == current_user
  end

  # 記憶したURL (もしくはデフォルト値) にリダイレクト(フレンドリーフォワーディング)
  def redirect_back_or(default)
    redirect_to(session[:forwarding_url] || default)
    session.delete(:forwarding_url)
  end

end

task.rbはこのようになっています

続きを読む

知っておくと便利なGoogle検索のテクニック(プログラミング)

駆け出しエンジニアが知っておくと便利なGoogle検索のテクニック

1:マイナス検索

Dockerについて書かれたコンテンツを検索したいが、
「PHP」という語を含むコンテンツは結果から除外したい場合は、
マイナス(-)記号の後に除外したい語を続けて検索します。

使用が想定されるケース:Rails+Dockerについて調べたいが、PHPについての記事は省きたい時など

検索例: Docker -PHP

2:完全一致検索

GoogleでDockerについて説明されたコンテンツを検索するとします。検索ボックスに「Docker」とだけ入力するのではなく、
これがフレーズであることを明示して検索する方法があります。それには次のようにフレーズを二重引用符で括って検索します。

使用が想定されるケース:余計なページを省きたいとき↓1/3カットできている。

 

続きを読む