- 投稿日:2021-01-17T22:38:35+09:00
Swift チャットアプリのチャット画面が作りたい!
チャットアプリのチャット画面に必要なもの
コロナ禍の中なかなか就職が決まらず暇なので、チャットアプリのチャット画面を作り方を記事にしたいと思います。
チャット画面に最低限必要なものってなんだと思いますか?
今回は僕が勝手に思うチャット画面に最低限必要なもの
で実装していきます。
必要なコンポーネントは以下tableView: メッセージを一覧表示するのに使います。
MessageCell: プロフィールとかメッセージをまとめます。
profileImageView: プロフィール画像を表示をします。
messageLabel: メッセージの表示をします。他にも送信時間表示用のlabelとかは?と思われると思いますが、データベースとか使って実際にメッセージの送受信をするわけではないので今回はこれだけにします。
実装
まずはViewControllerの方から
class ViewController: UIViewController { private let tableView = UITableView() //メッセージを格納する用の配列 private var messages = [String]() override func viewDidLoad() { super.viewDidLoad() initTableView() initMessages() view.addSubview(tableView) } //tableViewの設定 private func initTableView() { tableView.tableFooterView = UIView() tableView.separatorStyle = .none tableView.register(MessageCell.self, forCellReuseIdentifier: MessageCell.id) tableView.delegate = self tableView.dataSource = self tableView.frame = view.bounds } //messagesにメッセージを追加 private func initMessages() { messages.append("こんにちは") messages.append("今日の12時ごろ予定空いてますか?") messages.append("ひまですね") messages.append("寿限無(じゅげむ) 寿限無(じゅげむ) 五劫(ごこう)のすりきれ 海砂利(かいじゃり)水魚(すいぎょ)の水行末(すいぎょうまつ) 雲来末(うんらいまつ) 風来末(ふうらいまつ) 食(く)う寝(ね)るところに 住(す)むところ やぶらこうじの ぶらこうじ パイポ パイポ パイポの シューリンガン シューリンガンの グーリンダイ グーリンダイの ポンポコピーのポンポコナの 長久命(ちょうきゅうめい)の長助(ちょうすけ)") } } extension ViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messages.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: MessageCell.id, for: indexPath) as! MessageCell cell.message = messages[indexPath.row] return cell } }
initTableView()
の中を見ていきましょう。
tableFooterView = UIView()
は要素数以上の時に表示される空のcellを消すためです。
separatorStyle = .none
はcellとcellの間の薄い灰色のボーダー線を消します。
register
はカスタムセルを表示するためです。
こちらを参照してください。
コードでカスタムセルを使う時register(_:forCellReuseIdentifier:)関数を入れそびれていた
ViewControllerの中についての説明はこれくらいですかね。次はカスタムセルを作っていきます。
Message.swiftclass MessageCell: UITableViewCell { static let id = "MessageCell" public var message: String? { didSet { messageLabel.text = message } } private let profileImageView: UIImageView = { let imageView = UIImageView() imageView.image = #imageLiteral(resourceName: "image.jpeg") imageView.layer.masksToBounds = true imageView.layer.cornerRadius = 25 return imageView }() private let backView: UIView = { let view = UIView() view.backgroundColor = .opaqueSeparator view.layer.cornerRadius = 20 view.layer.masksToBounds = true return view }() private let messageLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 16) // labelの行数を指定 label.numberOfLines = 0 return label }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addSubview(profileImageView) addSubview(backView) backView.addSubview(messageLabel) setupAutoLayout() } private func setupAutoLayout() { profileImageView.translatesAutoresizingMaskIntoConstraints = false backView.translatesAutoresizingMaskIntoConstraints = false messageLabel.translatesAutoresizingMaskIntoConstraints = false let constraints = [ profileImageView.topAnchor.constraint(equalTo: topAnchor, constant: 10), profileImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10), // profileImageView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10), profileImageView.widthAnchor.constraint(equalToConstant: 50), profileImageView.heightAnchor.constraint(equalToConstant: 50), backView.topAnchor.constraint(equalTo: profileImageView.topAnchor), backView.leadingAnchor.constraint(equalTo: profileImageView.trailingAnchor, constant: 5), backView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10), backView.widthAnchor.constraint(lessThanOrEqualToConstant: 250), messageLabel.topAnchor.constraint(equalTo: backView.topAnchor, constant: 8), messageLabel.leadingAnchor.constraint(equalTo: backView.leadingAnchor, constant: 8), messageLabel.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: -8), messageLabel.trailingAnchor.constraint(equalTo: backView.trailingAnchor, constant: -8), ] NSLayoutConstraint.activate(constraints) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
profileImageView
とbackView
とmessageLabel
の宣言をしています。
クロージャでまとめるといいですね。
backView
はmessageLabel
に直接背景色を指定してしまうと背景と文字の間に余白がなくなって見ずらいのでいい感じに余白を作るために使います。
setupAutoLayout
の中を見ていきましょう。
各view
にtranslatesAutoresizingMaskIntoConstraints = false
という記述があります。
これをしないとautolayout
が使えないことがあるらしいです。
Auto Layoutをコードから使おう
constraints
からはautoLayout
でレイアウトを設定しています。
配列でまとめているのでNSLayoutConstraint.activate()
でまとめて有効にできます。
一部分だけ変更したい場合は[viewの変数名].topAnchor.constraint(equalTo: topAnchor).isActive = trueでできます。
まとめ
今回は相手側だけになりましたが制約を変更すれば自分の方も作れます。
もっと簡単にできる方法があれば教えてください。
わざわざ自分で実装するのめんどくさいという方はMessageKit
を調べてみてください。冒頭でも言ったように就職先募集してます。
あー、優しい企業様就職先をください!
- 投稿日:2021-01-17T20:31:01+09:00
【Swift】Hello Swift!と表示させる
はじめに
現在、書籍を使ってSWiftの勉強をしています。
備忘録として記事を書きます。Labelを配置
①project navigatorからファイルの一覧表示
②Main.storyboardを選択
③View Controller Scene▼
View Controller▼
Viewを選択
④Libraryをクリック
Library画面がポップアップで表示される。
⑤検索窓にLabelと入力する⑥検索されたLabelをstoryboardの中央にドラッグ&ドロップ
オートレイアウトを設定
①配置したLabelをクリック
②Xcode右下にあるAlignをクリック
③[Horizontally in Container]と[Vertically in Container]にチェックを入れる。
[Horizontally in Container]で画面中央から水平方向の距離を入力。
⇨[0]であれば、左右の中央に配置される。
[Vertically in Container]で画面中央から垂直方向の距離を入力
⇨[0]であれば、上下の中央に配置される。
④[Add 2 constraints]をクリックして、制約を反映。Labelとプログラムの関連付け
①Main.storyboardを選択、エディタの表示
②Labelからエディタへドラッグ&ドロップ
⇨Labelの上にマウスポインタを置いた状態で、「control」キー+クリックを押しながら、右方向へドラッグ(引っ張ると青いラインが出る)。エディタの最後にある中括弧のすぐ上までラインを伸ばす。
③関連付けの設定を行うためのダイアログが表示される。この画面にて、Labelとプログラムをどのような名前で関連付けるかを設定。
④[connect]をクリックすると↓のようにコードが追加されます。これがLabelとの関連付けを示すコードになる。@IBOutlet weak var outputLabel: UILabel!Labelに文字をセットするコードを書く
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. outputLabel.text = "Hello Swift!" } @IBOutlet weak var outputLabel: UILabel! }以上です。
- 投稿日:2021-01-17T20:14:17+09:00
FireStoreでサブコレクションを追加 [Swift]
サブコレクションとは、ドキュメント内のコレクションのことです。
これを新しく追加するには、ドキュメント内のサブコレクション内のドキュメントを作ることで、自動で生成されます。たとえば、国コレクション内に”japan”というドキュメントがある場合、
let db = Firestore.firestore() db.collection("countries") .document("japan") .collection("prefectures") // サブコレクションであるprefecturesがない場合、自動でリストが生成される。 .document("osaka") .setData([ capital: "osaka", specialty: "takoyaki" ]) { err in if let err = err { print("Error writing document: \(err)") } else { print("Document successfully written!") } }これでjapanドキュメントの中にprefecturesが生成され、県庁所在地と名物の情報をもったosakaというドキュメントが追加されます。
セキュリティルールの追加をお忘れなく。
?
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.comCore MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。
- 投稿日:2021-01-17T19:55:20+09:00
SceneEditorから追加したSCNActionに、コードからアクセスする
SCNActionはコードからもしくはSceneEditorから追加できます。
SceneEditorから追加する方法はApple Engineさんの以下の記事がわかりやすいかと思います。iOS で SceneKit を試す(Swift 3) その15 - Scene Editor の Action Editor を使ってみる
SceneEditorで追加したアクションをコードからリピートしたり組み合わせたりしたい時に。
ノードがアクションを持っているかどうかの確認
node.hasActionsノードが持っているアクションのKeyの確認
SceneEditorからアクションを追加した場合、英数字の文字列がデフォルトで割り当てられます。
node.actionKeysアクションの取得
たとえば、ノードに割り当てられているアクションの最初のものを取得するには以下
let actionFromNode = node.action(forKey: node.actionKeys[0])取得したアクションは、SCNActionとして再利用できる
anotherNode.runAction(actionFromNode)?
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.comCore MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。
- 投稿日:2021-01-17T19:51:28+09:00
Swift UIScrollViewの使い方
UIScrollView
をコードで実装独学でアプリ制作しているんですけど、そういえば
scrollView
使ったことないなと思ったので勉強しました!
まず、全く調べずにscrollView
を使ってみようとしました。
そのコードがこちらclass ViewController: UIViewController { private let label = UILabel() override func viewDidLoad() { super.viewDidLoad() let scrollView = UIScrollView() scrollView.frame = .init(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height) view.addSubview(scrollView) scrollView.addSubview(label) label.text = "hello world" label.frame = .init(x: 0, y: 0, width: 100, height: 50) label.center = scrollView.center } }結果はスクロールできませんでした。
label
はscrollView
がちゃんと表示されているか確認するために追加しています。なんで!?と思い調べてみると
contentSize
というものを指定しないといけないらしい。
contentSize
はスクロール領域を決めるらしい。
ということで修正したものがこちらclass ViewController: UIViewController { private let label = UILabel() override func viewDidLoad() { super.viewDidLoad() let scrollView = UIScrollView() //scrollViewの大きさを設定。 scrollView.frame = .init(x: 0, y: 0, width: view.frame.size.width * 2, height: view.frame.size.height * 2) //スクロール領域の設定 scrollView.contentSize = CGSize(width:view.frame.size.width * 2, height:view.frame.size.height * 2) //scrollViewをviewのSubViewとして追加 view.addSubview(scrollView) scrollView.addSubview(label) label.text = "hello world" label.frame = .init(x: 0, y: 0, width: 100, height: 50) label.center = scrollView.center } }これでどうだ!と思いビルドしましたがスクロールできませんでした。
さらに調べると、
frame
がcontentSize
より小さくないといけないみたい。class ViewController: UIViewController { private let label = UILabel() override func viewDidLoad() { super.viewDidLoad() let scrollView = UIScrollView() //scrollViewの大きさを設定。 scrollView.frame = .init(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height) //スクロール領域の設定 scrollView.contentSize = CGSize(width:view.frame.size.width * 2, height:view.frame.size.height * 2) //scrollViewをviewのSubViewとして追加 view.addSubview(scrollView) scrollView.addSubview(label) label.text = "hello world" label.frame = .init(x: 0, y: 0, width: 100, height: 50) label.center = scrollView.center } }結果は...いけたーーーー!!!
まとめ
UIScrollView
を使うときは
contentSize
を指定しないといけない
contentSize
はframe
より大きくないといけないということに注意して実装しましょう!
引用
- 投稿日:2021-01-17T16:47:31+09:00
[Swift]アプリアイコンの設定をしたのに反映されない時の対処法
困っていたこと
このようにAppIconにアイコンを設定したのに、いざシミュレーターや実機テストで確認してみると、アイコン画像が初期画像のまま変わっていない時の解決策について
調べて出てきた再起動、アプリを削除して再インストール、Clean Build Folderをしても解決できませんでした。解決した方法
Assets.xcassetsをクリック→AppIconをクリックし、
この画像のTarget Membershipの一番上の部分にチェックを入れると、変更されます。
ここのチェックが外れると、初期画像になってしまうようです。最後に
同じような事例で、他の解決方法、ご指摘などあれば気軽にコメントお願いします!
- 投稿日:2021-01-17T16:09:01+09:00
[Swift] Realmを実装して分かったこと色々
はじめに
Realmを以下の記事を参考に実装しました。
https://qiita.com/pe-ta/items/616e0dbd364179ca284b
以下のリンクから動き確認できます。
https://twitter.com/vex3ex5frd2xcvg/status/1350637210106699777?s=21
そこから色々調べてみたので、自分なりに理解した事を書いてみようと思います。
実装の手順などは、以下の記事から確認してください。実装
① importする
まずは
RealmSwift
をimportします。
RealmSwift
が必要な箇所でそれぞれimportしてみてください。
はじめはエラーになりますので、1度ビルドする事でimport出来ます。ViewController.swiftimport UIKit // RealmSwiftをimportするとエラーになるが、ビルドしたら治る import RealmSwift② モデルクラスの作成
ファイルの追加でswiftファイルを作成してください。
このファイルでは、Realmで扱うデータの項目とその型を定義します。
要は、このプロパティに値を保存していくイメージになります。
Realmモデルのプロパティには@objc
とdynamic
をつける必要があります。TodoModel.swiftimport Foundation import RealmSwift class TodoModel: Object { @objc dynamic var koumoku: String? = nil }③ viewControllerに変数を用意
Results
は「オブジェクトから返される Realm の自動更新コンテナ型」だそうです。
この変数にデータを追加していくことになります。ViewController.swift// 作成したTodoModel型の変数を用意。 // Realmから受け取るデータを入れる変数 var itemList: Results<TodoModel>!④ viewDidLoadでインスタンス化
今回使用するRealmをインスタンス化して使えるようにします。
次に、object()
を使用します。これは()内に指定したデータを全て取得できるものなので、
取得を行い、取得したデータを③で作成した変数に入れます。ViewController.swiftoverride func viewDidLoad() { super.viewDidLoad() // Realmをインスタンス化する let realm = try! Realm() // objects()はRealmに保存されている指定されたデータを全て取得する! // object().filter()でさらにフィルタリングして指定することもできるそうです。 self.itemList = realm.objects(TodoModel.self) }⑤ データを追加して保存していく
今回はbuttonを押したらtextFieldに書いた内容が追加されるようにします。
追加・保存を行いたいAction内で書いてみてください。1.追加していく場所は、②で作成したモデルクラス内のプロパティになりますので、モデルクラスをインスタンス化していきます。
2.textField.text
を②で作成したkoumoku
プロパティに入れます。
3.buttonAction内でもRealmを使うので、viewDidLoad内で作成したように、Realmをインスタンス化します。
4.realm.write
はRealmインスタンスを最新版に更新し、該当する場合は通知を作成すると公式ドキュメントにありました。
2でデータを更新しているので、realm.write
で最新のものを取得しているわけです。
realm.add()
は管理されていないオブジェクトを()内のRealmに追加します。
つまり、realm.add()
で管理されてない(追加したデータ)をRealmに追加して、
realm.write
でその最新バージョンを取得しているわけです。ViewController.swift@IBAction func addButton(_ sender: Any) { // 1.モデルクラスをインスタンス化。これでアクセスできるようになる! let instanceTodoModel: TodoModel = TodoModel() // 2.textFieldの値をぶち込む instanceTodoModel.koumoku = self.textField.text // 3.Realmをインスタンス化してデータベースを取得!viewDidLoadでも行ったやつ let realm = try! Realm() // 4.textFieldの値をデータベースに追加する // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。 try! realm.write { realm.add(instanceTodoModel) } self.tableView.reloadData() }⑥ TableViewの実装
itemList
にRealmから受け取ったデータが入っているので、それを使用してTableViewCellを作成していきます。ViewController.swiftextension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.itemList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) let item: TodoModel = self.itemList[indexPath.row] cell.textLabel?.text = item.koumoku return cell }⑦ 削除機能
Viewcontroller.swiftfunc tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { // この中でもRealmを使えるようにインスタンス化 let realm = try! Realm() if editingStyle == .delete { // 削除したいデータを検索する。今回はdeleteしたいcellのindexpath.row番目の項目を削除したいので、それをobjectで指定。 let deleteItem = realm.objects(TodoModel.self)[indexPath.row] do{ // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。 try realm.write{ // 追加の時のaddの削除版 realm.delete(deleteItem) } }catch{ print("Error") } } tableView.reloadData() }実際のコード
ViewController.swiftimport UIKit // RealmSwiftをimportするとエラーになるが、ビルドしたら治る import RealmSwift class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet weak var textField: UITextField! @IBOutlet weak var tableView: UITableView! // 作成したTodoModel型の変数を用意。 // Realmから受け取るデータを入れる変数 var itemList: Results<TodoModel>! override func viewDidLoad() { super.viewDidLoad() // Realmをインスタンス化する let realm = try! Realm() // objects()はRealmに保存されている指定されたデータを全て取得する! self.itemList = realm.objects(TodoModel.self) } @IBAction func addButton(_ sender: Any) { // モデルクラスをインスタンス化。これでアクセスできるようになる! let instanceTodoModel: TodoModel = TodoModel() // textFieldの値をぶち込む instanceTodoModel.koumoku = self.textField.text // Realmをインスタンス化してデータベースを取得!viewDidLoadでも行ったやつ let realm = try! Realm() //Realmインスタンスからaddを叩くと、データベースにレコードが追加される // textFieldの値をデータベースに追加する // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。 try! realm.write { realm.add(instanceTodoModel) } self.tableView.reloadData() } } extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.itemList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath) let item: TodoModel = self.itemList[indexPath.row] cell.textLabel?.text = item.koumoku return cell } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { let realm = try! Realm() if editingStyle == .delete { // 削除したいデータを検索する。今回はdeleteしたいcellのindexpathの項目を削除したいので、それをobjectで指定。 let deleteItem = realm.objects(TodoModel.self)[indexPath.row] do{ // write は refresh() が呼び出されたかのように Realm インスタンスを最新の Realm バージョンに更新し、該当する場合は通知を生成します。 try realm.write{ realm.delete(deleteItem) } }catch{ print("Error") } } tableView.reloadData() } }TodoModel.swiftimport Foundation import RealmSwift class TodoModel: Object { @objc dynamic var koumoku: String? = nil }起動してみた
ツイートしてあるので、リンク貼っておきます。
https://twitter.com/vex3ex5frd2xcvg/status/1350637210106699777?s=21参考サイト
https://qiita.com/pe-ta/items/616e0dbd364179ca284b
https://naoya-ono.com/swift/realm-update-delete/
- 投稿日:2021-01-17T12:52:00+09:00
iosアプリ開発に便利なライブラリ一覧
概要
iosアプリ開発において、簡単に便利なライブラリを紹介します。
ライブラリのインストールはcocoa podsを利用しています。目次
1.Alamofire
2.AlamofireImage
3.APIkit
4.Reachability.swift
5.ObjectMapper
6.Cadable
7.Rswift
8.lottie-ios
9.PKHUD
10.GradientCircularProgress
11.Realm Swift
12.RxSwift
13.promiseKit
14.Bright-future
15.swiftStoreKit
16.Graphs
17.SwiftDateネットワーク系
Alamofire
アプリからネットワーク通信をしたい場合、定番なツール
swift標準機能のURLRequestを使用するより、シンプルで書きやすいAlamofireImage
URLを指定して、ネットワーク上の画像を取得できる
APIkit
シンプルなコードが書ける
ネットワーク接続監視系
Reachability.swift
クロージャやローカル通知で接続状況の変化を受け取ることができる
デコーダ系
ObjectMapper
デコーダとして定番
Cadable
swift標準のデコーダ
リソースの定義系
Rswift
ソースコードの文字列を始めとするリソースの定義を構造体を使って自動的にリストアップしてくれる
アニメーション系
lottie-ios
リッチなアニメーションを作ることができる
インジケーター系
ソースコードの文字列を始めとするリソースの定義をstructを使って自動的にリストアップしてくれる
PKHUD
HUDを表示できる
GradientCircularProgress
データベース系
Realm Swift
データベースのコードをかんたんに書ける
アプリ自身にデータベースを持ち、サーバー側のデータベースと動機できるため、オフライン状態でもアプリを動作できる。
リレーションも使用可非同期処理系
RxSwift
非同期処理のイベントを受け取ることができる
promiseKit
シンプルに非同期処理を実現できる
Bright-future
シンプルに非同期処理が書けるが、日本語記事が少ない
課金系
swiftStoreKit
簡単に課金処理が作れる
グラフ系
Graphs
簡単アプリでグラフを作成できる
日付系
SwiftDate
簡単に日付処理ができる
- 投稿日:2021-01-17T08:33:29+09:00
プログラミングで数学検定1級は合格できるのか
はじめに
この記事で取り扱っているのは、1~5問目です。(全7問中)
数検1級の難易度は
大学程度・一般レベル。日本数学検定協会によると、合格率は5.7%で、すべて記述式だそう。東大の入試問題よりしばしば難しいとも言われます。
どの問題を解くのか
数学検定1級1次試験 サンプル問題 のうち何問かを解いていこうと思います。(模範解答はここから入手できます。
実行環境
Python......paiza.io
FORTRAN......AtCoder コードテストの中のABC187のコードテスト実際に解いていきましょう
1問目
問題1
2018n ≡ 2 mod(1000) を満たす正の整数nの最小値を求めよ。となる。まず、modとはどういうものだろうか。
modとは
p ≡ q(mod n)のとき、p-qがnで割り切れる。なんとなくわかりましたか?
では、例をみてみましょう。例
3 ≡ 8(mod 5)
3-8は5で割り切れます。こんな感じの記号です。
これを全探索(全てのパターンを試すアルゴリズム)で解いていこうと思います。(本当は1桁目で分類>2桁目で分類みたいな感じでとくのだろう)
Python
プログラム
n = 1 while True: if (2018*n-2)%1000 == 0: break n += 1 print(n)出力
389
FORTRAN
プログラム
program question1 do n = 1,1000 !ここでは、mod 1000 なので、nが1001以上の値を取らないことが証明できます。 if (mod((2018*n-2),1000) == 0) then print '(i0)', n end if end do end出力
389 889よって、最も小さい389が答えだと考えられます(最初から1000と2018が偶数であるから500まで全探索でも良いのですが。)。
Swift
プログラム
var n = 0 while n < 1001{ if (2018*n-2)%1000 == 0{ print(n) break } n += 1 }while文での実装です。
出力
389
解答を見たら正解でした。
2問目
tan(2 Arctan (1/3)+Arctan(1/12))を求めなさい。ただし、Arctan xはtan xの逆関数を表し、-π/2 < Arctan x < π/2 とします。
「Arctanはtanの逆関数」とは?
この記事に詳しく載っています。
これは普通に計算して、近い値を見つけていきたいと思います。
Python(精度 低)
プログラム
import math inside = 2*math.degrees(math.atan(1/3))#tanの中身 inside += math.degrees(math.atan(1/12)) print(math.tan(math.radians(inside)))出力
0.8888888888888887
だいたい、8/9くらいでしょうか(正解でした)。
本当はArctanの加法定理を使うのかな......Python(精度 UP)
<方針>
- Arctanの加法定理を実現しよう
- 小数は誤差が出やすいので、分数で考えよう
- 上の二つの条件を満たす関数を作ろう。Wikipediaにはこうある。
\arctan u+\arctan v=\arctan \left({\frac {u+v}{1-uv}}\right){\pmod \pi },\qquad uv\neq 1\,.ここでは、-π/2~π/2でのみ定義しているため、(mod π)をなくして考える。u=a/b,v=c/dとして考える。問題ではその後、tanでまた元に戻しているため、(u+v)/(1-uv)のみ考えれば良い(tan(arctan(x)) = x)。結局、答えは(u+v)/(1-uv)なので、これを出力するプログラムを考える。
とりあえず、こんな関数を作ってみました。
from fractions import Fraction def arctan_sum(a,b,c,d): u = Fraction(a,b) v = Fraction(c,d) return ((u+v),(1-u*v))戻り値はタプルです。下のように書くと、
プログラム
from fractions import Fraction def arctan_sum(a,b,c,d): u = Fraction(a,b) v = Fraction(c,d) return ((u+v),(1-u*v)) left = arctan_sum(1,3,1,3) total = arctan_sum(left[0],left[1],1,12)出力結果
8/9綺麗に答えが出ました。
3問目
xyz空間内の4点(1,-4,1),(2,2,2),(2,-6,-3),(3,-2,-1)を頂点に持つ四面体の体積を求めよ。
サラスの公式を使って解きます。まず、(0,0,0)(x1,y1,z1),(x2,y2,z2),(x3,y3,z3)を頂点に持つ四面体の体積を求める関数を作る。しかし、これは(0,0,0)を頂点に持つ四面体を考えなければならないので、x1~z3を手計算(一番早そうなので)で求めていきたいの思います。
Python
関数
from fractions import Fraction def sarasu(x1,y1,z1,x2,y2,z2,x3,y3,z3): return Fraction(abs(y1*z2*x3+z1*x2*y3+x1*y2*z3-z1*y2*x3-x1*z2*y3-y1*x2*z3),6)プログラム全体
from fractions import Fraction def sarasu(x1,y1,z1,x2,y2,z2,x3,y3,z3): return Fraction(abs(y1*z2*x3+z1*x2*y3+x1*y2*z3-z1*y2*x3-x1*z2*y3-y1*x2*z3),6) print(sarasu(1,6,1,1,-2,-4,2,2,-2))出力結果
3
これもあっさり答えが出ました。(正解でした。)
4問目(1)
3次正方行列 A = \left( \begin{array}{ccc} 4 & 1 & 1 \\ 1 & 2 & 1 \\ 1 & 1 & 2 \end{array} \right) について次の問いに答えなさい。①固有値を求めなさい。Python
Pythonで固有値を求めることができるので、求めていこうと思います。
プログラム
import numpy as np import numpy.linalg as LA a = np.array([[4,1,1],[1,2,1],[1,1,2]])#固有値を求めたい行列 aeig_val = LA.eig(a)[0] aeig_val = np.sort(aeig_val) print(aeig_val)出力結果
[1. 2. 5.]リストにしようとすると、誤差が出るため、このような結果にしました。(答えは1,2,5なので、あってます。)
4問目(1)進化版
replaceで解答の形に変えました。
Python
プログラム(進化版)
import numpy as np import numpy.linalg as LA a = np.array([[4,1,1],[1,2,1],[1,1,2]])#固有値を求めたい行列 aeig_val = LA.eig(a)[0] aeig_val = np.sort(aeig_val) ans = str(aeig_val) ans = ans.replace("[","").replace(".]","").replace(". ",", ") print(ans)出力結果
1, 2, 54問目(2)
固有値問題を数値的に解く - 高知大学、行列の累乗、3 単位行列、行列の転置(行列) などを参考にして、求めていきたいと思います。これはやるだけで、大丈夫です。
Python
プログラム
import numpy as np import numpy.linalg as LA A = np.array([[4,1,1],[1,2,1],[1,1,2]]) I = np.array([[1,0,0],[0,1,0],[0,0,1]]) A3 = np.linalg.matrix_power(A, 3)#A^3 A2 = np.linalg.matrix_power(A, 2)#A^2 ans = A3-8*A2+18*A-12*I#そのまま演算子で計算 print(ans)出力結果
[[2 1 1] [1 0 1] [1 1 0]]わかりやすく書くと、
\left( \begin{array}{ccc} 2 & 1 & 1 \\ 1 & 0 & 1 \\ 1 & 1 & 0 \end{array} \right)(これもまた正解でした)
5問目(1)
一定の期間内における機械の故障回数はポアソン分布に従うことが知られています。ある会社では2つの機械A, Bを使用しており、1年間で故障する回数が機械Aが平均2.5回、機械Bは平均4.5回のポアソン分布に従うとき、次の問いに答えなさい。ただし、A,Bが1年間に故障する回数は互いに独立であるとし、解答の際は1-6-6にあるポアソン分布表を用い、答えは小数第4位を四捨五入して小数第3位まで求めなさい。
①機械Aが1年間に4回以上故障する確率を求めなさい。
ポアソン分布というのは......
「ポアソン分布を表す確率関数は,
P(k) = (e^{-k}*λ^k) / k!です。
つまり,単位時間あたり平均 λ 回起こるようなランダムなイベントが,単位時間に k 回発生する確率が P(k) です。」(高校数学の美しい物語 ポアソン分布の意味と平均・分散 より抜粋)
この問題では、壊れた回数が4回未満になる確率を全体から引く。このとき、λが2.5、kが0~3だとわかる。
Python
プログラム
zero_three = 0.0821+0.2052+0.2565+0.2138#足しただけ print(round((1-zero_three)*1000)/1000)出力結果
0.242
正解でした。
5問目(2)
一定の期間内における機械の故障回数はポアソン分布に従うことが知られています。ある会社では2つの機械A, Bを使用しており、1年間で故障する回数が機械Aが平均2.5回、機械Bは平均4.5回のポアソン分布に従うとき、次の問いに答えなさい。ただし、A,Bが1年間に故障する回数は互いに独立であるとし、解答の際は1-6-6にあるポアソン分布表を用い、答えは小数第4位を四捨五入して小数第3位まで求めなさい。
②機械A,Bが合わせて8回以上故障する確率を求めなさい。
まず、平均2.5回、4.5回のポアソン分布の値をリストにします。次に、故障した回数が8未満になる確率を求め、全体から引きます。
Python
プログラム
A = [0.0821,0.2052,0.2565,0.2138,0.1336,0.0668,0.0278,0.0099,0.0031,0.0009,0.0002]#平均2.5回のポアソン分布 B = [0.0111,0.0500,0.1125,0.1687,0.1898,0.1708,0.1281,0.0824,0.0463,0.0232,0.0104]#平均4.5回のポアソン分布 ans = 0 for i in range(8): for j in range(i+1): ans += A[i-j]*B[j] print(round((1-ans)*1000)/1000)出力結果
0.401
正解でした。
結論
合格します(合格ラインは5問)!ただ、普通に計算した方がプログラムを組むよりも早い問題もあります。
参考文献
- Qiita Markdown 書き方まとめ
- 数学検定 算数検定 ホームページ
- 日本 NAG Fortran入門
- Yahoo 知恵袋 エラーに関する質問
- Tech Academy 繰り返し処理!Swiftで書くwhile/for文の使い方【初心者向け】
- Pythonで三角関数を計算(sin, cos, tan, arcsin, arccos, arctan)
- Wikipedia 逆三角関数
- fractions --- 有理数
- LaTeXコマンド集 行列
- NumPyのsortとargsort関数で任意の行・列を基準にソート
- 固有値問題を数値的に解く - 高知大学
- 行列の累乗
- 3 単位行列、行列の転置(行列)
- Pythonで小数・整数を四捨五入するroundとDecimal.quantize
注意
- この記事は数学検定でのカンニングを推奨するものではありません。悪用しないでください。