- 投稿日:2019-10-01T23:32:12+09:00
オブジェクト指向のクラスの書き方
オブジェクト指向とは?
プログラムという仮想の世界を、現実世界の実体(オブジェクト)に合わせて、プログラムを書いていく、という考え方のこと。
その考え方に基づいてプログラムを書いていくことで、保守性が高くなる。
例えばゲームに登場させるモンスターを30体用意しなきゃいけない、ということになったとき、
30体全部を一体ずつ作成するのは大変です。オブジェクト指向で書かないとどうなる?
今学んでいるのがPHP言語なのでPHPで以下の説明コードを書いていきます。
一般的なゲームでは、
モンスターの名前、属性、見た目、HP、攻撃力、防御力
などなどが必要です。
それらを連想配列で用意していきます。
// モンスターたち格納用配列 $monsters = array(); $monsters[] = array( 'name' => ‘ファイアーマン’, ‘attribute’ => ‘火’, 'hp' => 100, 'img' => 'monster01.png', 'attack' => mt_rand(20, 40) ’defense’ => mt_rand(50,70) ); $monsters[] = array( 'name' => ‘ウォーターマン’, ‘attribute’ => ‘水’, 'hp' => 200, 'img' => 'monster02.png', 'attack' => mt_rand(30, 80) ’defense’ => mt_rand(20,40) ); $monsters[] = array( 'name' => ‘ウッドマン’, ‘attribute’ => ‘木’, 'hp' => 300, 'img' => 'monster03.png', 'attack' => mt_rand(10, 30) ’defense’ => mt_rand(90,150) ); //以下略こんな風に30体作っていくことになると思うのですが、これを抽象化して
「共通点を集めて、1つの雛形(テンプレート)を作れば保守性が上がるんじゃない?」
ということが、オブジェクトとして考えるってことだと今の所理解しています。
==============================================
※保守性が高い、というのは以下の意味だと思っています。
- あとから読んだときにわかりやすい
- 変更しやすい、修正しやすい
- バグを生みにくい
=============================================
オブジェクト指向でモンスターのクラスを作成【準備編】
モンスターの共通点は今回の例でいうと
・名前
・タイプ(火タイプとか、水タイプとか)
・見た目
・HP
・攻撃力
・防御力になります。
これらはプロパティ(属性)というもので、
動きがあるものはメソッド(動き)と呼ばれます。攻撃はプロパティだけど、攻撃するはメソッド。
足が3本はプロパティだけど、走るはメソッド。という感じです。
①これらを予めモンスターの設計図として、テンプレートとして準備します。
このモンスターの共通点をクラスに入れ込みます。
この設計図が、クラスになります。②クラスの中にコンストラクタを作成します。
コンストラクタは、クラスをインスタンス化した時に実行されるメソッド。
※newしたときにプロパティを設定したい場合、適用する関数(マジックメソッド)③この設計図を元に、インスタンスを作成します。
僕のイメージですが、インスタンスの作成って
モンスター工場で、設計図を元にガッチャン!って金型でプレスして作るようなイメージでいるんですが
とにかく設計図を元に、インスタンスというものを作ります。
このインスタンスを作ることを「実体化」と言います。オブジェクト指向でモンスターのクラスを作成【コード編】
実際のコードは
// モンスターたち格納用 $monsters = array(); // クラス(設計図)の作成 class Monster{ // プロパティ public $name; public $attribute; public $hp; public $img; public $attack; public $defense; // コンストラクタ public function __construct($name, $attribute, $hp, $img, $attack,$defense){ // -> : アロー演算子は左辺から右辺を取り出す演算子 $this->name = $name; $this->attribute = $attribute; $this->hp = $hp; $this->img = $img; $this->attack = $attack; $this->defense = $defense; } }という感じです。
ひとまずこれでモンスターの設計図は出来上がり!
※アクセス権は一旦無視して作っています。さて、次にインスタンスの作成ですが、
// インスタンス生成 $monsters[] = new Monster('ファイアーマン', 100, 'monster01.png', mt_rand(20, 40),mt_rand(50,70)); $monsters[] = new Monster('ウォーターマン', 200, 'monster02.png', mt_rand(30, 80),mt_rand(20,40)); $monsters[] = new Monster('ウッドマン', 300, 'monster03.png', mt_rand(10, 30),mt_rand(90,150));という風になります。
【注意!】インスタンス生成時には、必ずnewを入れないといけません。これで原型は出来上がり。
モンスター工場で、設計図を元にガッチャン!ってプレスしてモンスターが生まれました。
ここまでのまとめ
- オブジェクトを作るには、設計図が必要です。
- その設計図は「クラス」と言います。
- クラスを元に出来上がるオブジェクトがインスタンス。
- クラスの中にコンストラクタを入れれば、インスタンス生成時に呼び出される。
- クラスにはプロパティと、メソッドを入れることができる。
- オブジェクト指向で作っておくと、後で修正や変更がしやすい。
(あとからやっぱり「MP」と「魔法攻撃する」を入れたいときには、MPのプロパティと魔法攻撃のメソッドをクラスに足すだけでインスタンスがそのプロパティとメソッドを持てる)感想
オモシロイと思ったのは
何かオブジェクトを作ろうと思ったとき、連想配列でも出来るんだ!ということです。
ただ連想配列のkey&valueの1セット1セットが独立しているわけではなく、全部揃ってそのオブジェクトを表している、、、という表現で合っているんでしょうか?連想配列の箱にただ順番にデータが入っているわけではなく、意味があってそのデータが入っているんですよね。
プロパティの情報が全部合わさって、一つの意味のあるクラスが出来上がる。というような。奥が深いです!
今回は以上です。
- 投稿日:2019-10-01T15:51:50+09:00
PHP Slim 環境構築(9) 設定ファイル
PHP Slim 環境構築(9) 設定ファイル
Introduction
前回は、ローカルS3(互換)をdockerで立てて、それにアクセスしてみました。
今回は、設定ファイルなどを少し整理してみます。変更点
ソースツリー
前回からの変更・追加ソースは以下の通りです。
$(PROJECTROOT) /compose /web_front Dockerfile local.conf (default.confからのrename) /web_hoge Dockerfile php.local.ini settings.local.php docker-compose-common.yml (docker-compose.ymlからのrename) docker-compose-local.yml /src /hoge /public index.php/web_front/Dockerfile
Nginxの設定ファイルを環境(local, developmentなど)毎に変更できるように修正しました。
docker-composeでenvironment, environmentkeyを指定します。
なお、environmentが環境、environmentkeyが環境内の枝番(developement-1とかlocal-hogebranchとか)です。/compose/web_front/DockerfileFROM nginx:1.17.3 ARG environment ARG environmentkey="" # settings COPY ${environment}.conf /etc/nginx/conf.d/default.conf RUN sed -i -e"s/{ENVKEY}/${environmentkey}/" /etc/nginx/conf.d/default.conf RUN deluser www-data \ && addgroup --system --gid 1000 www-data \ && adduser --system --home /var/www --no-create-home --uid 1000 --gid 1000 \ --disabled-password --disabled-login --shell /usr/sbin/nologin www-data EXPOSE 3128 EXPOSE 8443/web_front/local.conf
default.confからrenameしただけで中身は変更していません。
なお、開発用やテスト用サーバを立てる場合は、server_nameにサーバ名を指定することになります。
このとき、サーバ名に{ENVKEY}などを含めておくと、DockerfileでARG(environmentkey)と置換されます。/compose/web_front/local.conf...(略)... server { listen 3128; listen 8443 ssl; server_name hoge.localhost; ...(略).../web_hoge/Dockerfile
phpの設定と、DB接続情報などを環境毎に変更できるようにしました。
/web_front/Dockerfileと同様に、docker-composeでenvironment, environmentkeyを指定します。なお、php-fpmの設定は今回変更していませんが、php.iniと同様の方法で、/usr/local/etc/php-fpm.d/zz-overwrite.confなどに設定をコピーするようにすることで設定を変更することもできます。
/compose/web_hoge/DockerfileFROM php:7.3.9-fpm-alpine3.10 ARG environment ARG environmentkey="" ...(略)... # settings COPY settings.${environment}.php /var/www/settings.php RUN sed -i -e"s/{ENVKEY}/${environmentkey}/" /var/www/settings.php # PHP conf COPY php.${environment}.ini /usr/local/etc/php/conf.d/php.ini RUN apk del --purge .build-deps \ && docker-php-source delete \ && rm -rf /var/cache/apk/* \ && rm -rf /tmp/* RUN deluser www-data \ && addgroup -g 1000 -S www-data \ && adduser -u 1000 -D -S -G www-data www-data/web_hoge/php.local.ini
エラーログを出力するようにしています。出力先はphp-fpmのデフォルト設定である標準エラー出力になります。
したがって、docker-compose logsコマンドでエラーログを見ることができます。/compose/web_hoge/php.local.ini[PHP] log_errors = On display_startup_errors = On error_reporting = E_ALL upload_max_filesize = 256M/web_hoge/settings.local.php
/src/hoge/public/index.phpのDIコンテナの設定部分を抜き出しただけです。
/compose/web_hoge/settings.local.php<?php return [ 'userdb' => [ 'host' => 'mysql', 'dbname' => 'userdb', 'user' => 'scott', 'password' => 'tiger' ], 'logdb' => [ 'host' => 'postgresql', 'dbname' => 'logdb', 'user' => 'root', 'password' => 'hogehoge' ], 'redis' => [ 'host' => 'redis' ], 'dynamodb' => [ 'endpoint' => 'http://dynamodb:8000', 'region' => 'ap-northeast-1' ], 'storage' => [ 'endpoint' => 'http://storage:9000', 'region' => 'ap-northeast-1' ] ];docker-compose-common.yml, docker-compose-local.yml
前までのdocker-compose.ymlを環境依存の部分と非依存の部分で分けました。
そのため、docker-composeコマンドを実行する場合は、以下のように設定ファイルを指定する必要があります
(-fは指定した順序に読み込まれ、後に指定した設定によって上書きされます)。$ docker-compose -f docker-compose-common.yml -f docker-compose-local.yml builddocker-compose-common.ymlは旧docker-compose.ymlからサーバ名などの部分を取り除いた部分になります。
/compose/docker-compose-common.ymlversion: '3' services: web_front: build: context: ./web_front ports: - "80:3128" - "443:8443" volumes: - ../certs:/etc/certs:ro container_name: web_front networks: - private_net web_hoge: build: context: ./web_hoge volumes: - ../src/hoge:/var/www/hoge - ../src/vendor:/var/www/vendor container_name: web_hoge networks: - private_net redis: build: context: ./redis volumes: - redis-data:/var/lib/redis ports: - "16379:6379" sysctls: - net.core.somaxconn=1024 container_name: redis networks: - private_net mysql: build: context: ./mysql volumes: - mysql-data:/var/lib/mysql ports: - "13306:3306" container_name: mysql networks: - private_net postgresql: build: context: ./postgresql volumes: - postgresql-data:/var/lib/postgresql ports: - "15432:5432" container_name: postgresql networks: - private_net dynamodb: image: amazon/dynamodb-local container_name: dynamodb ports: - "18000:8000" networks: - private_net storage: image: minio/minio volumes: - storage-data:/data container_name: storage ports: - "19000:9000" environment: MINIO_ACCESS_KEY: minio MINIO_SECRET_KEY: miniminio command: server /data networks: - private_net volumes: redis-data: mysql-data: postgresql-data: storage-data: networks: private_net: driver: bridge ipam: driver: default config: - subnet: 172.28.0.0/24逆に、docker-compose-local.ymlはdocker-compose-common.ymlから取り除かれた部分になります。
/compose/docker-compose-local.ymlversion: '3' services: web_front: build: args: - environment=local - environmentkey= web_hoge: build: args: - environment=local - environmentkey= environment: XDEBUG_CONFIG: "remote_host=172.28.0.1" PHP_IDE_CONFIG: "serverName=hoge.localhost" domainname: localhostindex.php
以前のソースで、ContainerBuilder::addDefinitionsを呼び出したとき設定していたsettingsを、外部から呼び出してきてセットするように修正しています。
/src/hoge/public/index.php...(略)... /** @var Composer\Autoload\ClassLoader $loader */ $loader = require __DIR__ . '/../../vendor/autoload.php'; $loader->addPsr4('Hoge\\', __DIR__ . '/../lib'); $settings = require __DIR__ . '/../../settings.php'; $containerBuilder = new ContainerBuilder(); $containerBuilder->addDefinitions([ 'settings' => $settings, 'userdb' => function (ContainerInterface $container) {ここまでのソース
こちらでどうぞ。
- 投稿日:2019-10-01T15:35:17+09:00
ローカル開発環境をmampからdockerに移した話
やりたかった事、背景
・元々の開発環境はmampだった
・新しくプロジェクトを追加する時、スクリプト動かしてvhost記述して、みたいな感じでめんどかった
・port番号が8888のせいでめんどい時があった(設定次第で別にmampでもできる)
・上司にdocker環境を進められて、興味があった
・社内で使っていたdocker開発環境だと自分の環境ではxdebugが動かなかった。また、その環境はコンテナがプロジェクトファイルのhtdocsフォルダに紐つけられていて、プロジェクトを再配置するのがだるかったじゃあもうdockerで自分で環境作っちゃえ!!!
実際にやった事
・ローカル環境のhttps化(オレオレ)
・VirtualDocumentRootを使ってvhostをワイルドカード化した(超楽になった)
・xdebug動くようにした
・php5とphp7切り替えられるようにした
・mailhogつけた
・importがめんどかったのでdbのデータもディレクトリ写すだけでできるようにしたdbのデータだけはなぜかできなかったので誰かプルリク投げてください。。。
いろんなサイト参考にしていいとこ取りしまくりました。。すみません。。。
レポジトリはgithubに公開してます。
docker-compose up -d
で動きます。是非とも使用して、ガシガシ開発しましょう!!!
- 投稿日:2019-10-01T14:20:28+09:00
Webプロ コマンドまとめ
用語
用語 解説 ディレクトリ ほぼ「フォルダ」と同じ意味(厳密には違う) ホームディレクトリ パソコンに入っているアカウントごとに用意されているディレクトリ 基本的に作ったファイルはここの中に保存する(ワードやエクセルなどのファイルもそう) ディレクトリ表示
- lsとはlistの略
- 自分が今いるディレクトリの一つ下にあるディレクトリの一覧が表示される
ターミナルorコマンドプロンプトls
ディレクトリ移動
- cdとはchange directoryの略
- {ディレクトリ名}のディレクトリに移動
- {ディレクトリ名}は
ls
のコマンドを打ったときに出てくるディレクトリを入れるターミナルorコマンドプロンプトcd {ディレクトリ名} # 例 cd php7 cd Desktop
- 一つ上のディレクトリに移動
ターミナルorコマンドプロンプトcd ..
- ホームディレクトリに移動(次の2つのうちどちらでも良い)
ターミナルorコマンドプロンプトcd cd ~
サーバー起動
- PHPでサーバーを起動
- 起動後にlocalhost:{数字}にアクセスするとアクセスできる
- {ディレクトリ名}は
ls
のコマンドを打ったときに出てくるディレクトリを入れる- 大文字と小文字を打ち間違えるとうまく起動しない
ターミナルorコマンドプロンプトphp -S localhost:{数字} -t {ディレクトリ名} # 例 php -S localhost:8080 -t htdocs
- 投稿日:2019-10-01T13:12:25+09:00
メモ - GAE/SE php72,73 ローカル実行時の設定
php73@gae でローカルでテストするときのメモ。
php72/73 では dev_appserver.py が無くなったので、普通に php インストールしてテストする。
が、普通に
php -S localhost:8080とかやるだけだと、gaeにデプロイした時と違う挙動になる。
app.yamlruntime: php73 entrypoint: serve --workers=4 --enable-dynamic-workers index.phpindex.php<?php switch (@parse_url($_SERVER['REQUEST_URI'])['path']) { case '/': require 'hello.php'; break; case '/test': require 'test.php'; break; case '/dir/test': require 'dir/test.php'; break; default: http_response_code(404); exit('Not Found'); }とかのデバッグをローカルでやる場合、
は問題ないが
http://localhost:8080/dir/test
は
Not Found The requested resource /dir/test was not found on this server.となってしまう。
この場合、ビルトインウェブサーバーの起動時にルータースクリプトとして index.php を指定するとよい。
php -S localhost:8080 index.phpたぶん。
- 投稿日:2019-10-01T11:04:23+09:00
phpのvar_dumpとvar_exportの違いをよく聞かれるので説明してみる
<?php $hoge = [ 'aaa' => 'hoge', 'bbb' => 'foo', 'ccc' => 'bar', ]; var_dump($hoge); var_export($hoge);/////var_dump///// array(3) { ["aaa"]=> string(4) "hoge" ["bbb"]=> string(3) "foo" ["ccc"]=> string(3) "bar" } /////var_export///// array ( 'aaa' => 'hoge', 'bbb' => 'foo', 'ccc' => 'bar', )基本的には標準出力する分には同じです。
出力される構造としては上記のような違いになります。var_export関数は var_dump() に似ていますが、 返される表現が有効な PHP コードであるところが異なります。
公式の言い方をするとvar_exportは、このような「有効なPHPコード」という形式になります。
ちなみに有効なPHPコードとは?という疑問もあると思います。
var_exportの第二引数にtrueを指定すると変数を出力せずに変数の値を返します。なので、使用用途としてはログ出力時などに変数情報を文字列として出力するには
var_export()が適しています。ex) \Log::debug(var_export($hoge, true));var_dumpは配列の要素数や型も表示されるので用途別で使い分けましょう。
- 投稿日:2019-10-01T09:36:14+09:00
HomebrewでPHP7.2のインストール(Mac)
install php for mac
mac OS version : 10.14.4
Homebrew : 2.1.9参考1 : https://qiita.com/saken649/items/b5830de62211b600f7ee
参考2 : https://qiita.com/nemui_/items/cbf876db509e6a427541homebrewはインストールしてあることが前提
phpのデフォルトバージョン確認
$ php -v PHP 7.1.23 (cli) (built: Feb 22 2019 22:08:13) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies$ brew search php72 ==> Formulae php@7.2 $ brew install php@7.2 (前略) If you need to have php@7.2 first in your PATH run: echo 'set -g fish_user_paths "/usr/local/opt/php@7.2/bin" $fish_user_paths' >> ~/.config/fish/config.fish echo 'set -g fish_user_paths "/usr/local/opt/php@7.2/sbin" $fish_user_paths' >> ~/.config/fish/config.fish (後略)pathを通す(おらのシェルはfishなので,bashとは少しコマンドが違う)
$ echo 'set -g fish_user_paths "/usr/local/opt/php@7.2/bin" $fish_user_paths' >> ~/.config/fish/config.fish $ echo 'set -g fish_user_paths "/usr/local/opt/php@7.2/sbin" $fish_user_paths' >> ~/.config/fish/config.fish再読み込みして通るか確認
$ source ~/.config/fish/config.fish$ which php /usr/local/opt/php@7.2/bin/php $ php -v PHP 7.2.22 (cli) (built: Sep 14 2019 18:36:32) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.22, Copyright (c) 1999-2018, by Zend Technologiesインストール完了.
rbenvみたいにversion切り替えできるようにしたいなぁ...
- 投稿日:2019-10-01T08:16:30+09:00
macでdocker-composeを使ってPHPとnginxをすぐに使えるようにする方法
PHPの勉強用に「折角だからnginxをdockerで立てて使おう〜」と軽い気持ちでコンテナ立てて実行しようとしたところ「コンテナのnginxのドキュメントルートにどうやってファイル置くんだろ。」とか「もしかしてコンテナ入って置かないとダメ?」とか前知識が無くて全然うまく行かず。。
docker-composeを使って速攻で準備
出来ねぇ出来ねぇボヤいてたらwebエンジニアにdocker-composeを使って速攻でその辺の環境を作る方法を教えてもらいました。
コンテナを立てたい場所に下記のdocker-compose.yml
ファイルを作成します。[docker-compose.yml] ### nginxでphpをブラウザ上に表記するのに必要なコンテナ一式。 version: '3' services: app: image: laradock/php-fpm:2.2-7.2 # ローカルのカレントディレクトリに格納したファイルをコンテナの/var/phpappにマウントする volumes: - ./:/var/phpapp/ nginx: image: nginx:latest # 8080ポートから来た接続をコンテナの80番ポートに連携する ports: - "8080:80" volumes: # ローカルの./docker/nginx/nginx.confのをnginxコンテナの/etc/nginx/conf.d/default.confにマウントする - ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf # ローカルカレントディレクトリをコンテナの/var/phpappにマウント - ./:/var/phpapp/ mysql: image: mysql:5.7 # 33306ポートから来た接続をコンテナの3306番ポートに連携する ports: - 33306:3306 volumes: - ./testdata/:/data environment: MYSQL_DATABASE: app MYSQL_ROOT_PASSWORD: rootあとnginx.confの内容を下記にします。
これはローカルの.docker/nginx/nginx.conf
に作成してください。[nginx.conf] server { listen 80; server_name localhost; root /var/phpapp/web; index index.php index.html; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_pass app:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }nginx.confの方は深く説明しませんが、この設定にしておけばローカルのカレントディレクトリの
web
フォルダに格納したPHPファイルはちゃんと処理されてブラウザ上で表示されます。あとはdocker-composeファイルを起動させれば準備完了します!
$ docker-compose up -d
出来たものはこちらです。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 04e0f98cc4ef mysql:5.7 "docker-entrypoint.s…" 7 hours ago Up 7 hours 33060/tcp, 0.0.0.0:33306->3306/tcp memo_keizi_mysql_1 8c0639887fb3 laradock/php-fpm:2.2-7.2 "docker-php-entrypoi…" 23 hours ago Up 23 hours 9000/tcp memo_keizi_app_1 c3574c4c67b9 nginx:latest "nginx -g 'daemon of…" 34 hours ago Up 33 hours 0.0.0.0:8080->80/tcp memo_keizi_nginx_1
IMAGE
のところがdocker-composeのimage
で記述したものになっています。PHPをブラウザで表示させるところまで確認する
折角なので格納したPHPファイルがブラウザ上で表示されるところまで確認します。
※今回MySQLは使用しません。nginx.confで設定した
root /var/phpapp/web;
によりwebフォルダがドキュメントルートになります。
カレントディレクトリにwebフォルダを作成し、PHPファイルを格納します。$ ls web/ index.phpファイルの内容はありきたりですが、Hello World出力で。。
[index.php] <html> <head> <title>PHP Test</title> </head> <body> <?php echo '<p>Hello World</p>'; ?> </body> </html>
http://localhost:8080/
でアクセスすると、、問題なく出力されました。
このwebフォルダにPHPのファイルを入れてパス指定すれば問題なく起動します。終わりに
半端な知識で「nginxはコンテナで!PHPはローカルに入ってるからそれで勝手に処理してくれるでしょ!」くらいの軽い気持ちでやったら泥沼でした。。
- 投稿日:2019-10-01T00:38:44+09:00
【初心者向け】競技プログラミングざっくり入門【競プロ】
この記事の目的
競技プログラミング/プログラミングコンテストに参加し始めたばかりの自分が、コンテストや過去問を解く上で参考にしたサイト、困ったことなどをメモするほか、これから競技プログラミングに挑戦していこうという人たちの参考になれば。自分のレベル感としては最初の村を出たばかりで、ひのきのぼうと皮の盾装備。PHPerなので参考URLはPHP関連のものが多いです。競技プログラミングにおいてPHPerは少数派なので情報が少なく、それが動機ともなってこのような記事を書こうと思い至りましたが、実行速度や人気度などからC++, Pythonなどでもいずれやりたいなぁと思っています。
競技プログラミングとは
競技プログラミング(以下、競プロ)とは、プログラミング技術を競うコンテストのこと。いろいろな企業や団体が主催をしていて、世界中で毎日のように競技が開催されています。様々な言語の取り扱いがあり、自分の得意な言語でチャレンジ可能。オフラインのものは参加したことはありませんが、オンラインのコンテンスト問題は、与えられたお題に対して、正しい出力が期待されるコードを送信するだけで、機械的にジャッジされて得点や順位、レーティングが分かったりするので気軽に挑戦できるのが魅力かと思います。ここでは主にオンラインの競技プログラミングに関して取り上げています。
競プロいろいろ
国内サイト・大会
AtCoder
日本最大級の競プロサイト。yukicoder
中規模なプログラミングコンテストサイト。日本情報オリンピック(Japanese Olympiad in Infomatics(JOI))
高校生向けプログラミングコンテストの国際情報オリンピック(IOI)の代表選考のためのコンテスト。paiza プログラミングスキルチェック
エンジニア向けラーニング&転職サービスですが、スキルチェックとして競プロに近いテストをオンラインでたくさん受けられます。CODE VS
リクルートが主催するプログラミングコンテスト。海外サイト
LeetCode
アメリカ・カリフォルニア発の競プロサイト。英語と中国語に対応。HackerRank
アメリカにあるプログラミングコンテストサイト。Topcoder
アメリカのAppirio社が提供するプログラミングコンテストサイト。Codeforces
ロシアの大学 (Saratov State University) に所属するMike Mirzayanovらが実施するプログラミングコンテストサイト。CodeChef
Directi社が運営・提供するプログラミング学習サイト。Project Euler
数学の問題が出題されるようです。国際大会
Google Code Jam (GCJ)
Googleが実施するプログラミングコンテスト。Facebook Hacker Cup (FHC)
Facebookが実施するプログラミングコンテスト。ACM-ICPC 国際大学対抗プログラミングコンテスト
大学対抗のプログラミングコンテスト。1970年から始まり今に続く歴史あるコンテスト。2019 TopCoder Open
TopCoderが実施する祭典コンテスト。毎年開催され、年度によってURLも新設されるので注意が必要です。ICFP Programming Contest (ICFPC)
関数型プログラミング言語のカンファレンスが実施するコンテスト。Microsoft Imagine Cup
マイクロソフトが実施する学生向けのプログラミングコンテスト。国際情報オリンピック(International Olympiad in Informatics) (IOI)
高校生向けのプログラミングコンテスト。参加するには日本情報オリンピックで代表に選ばれる必要があります。AtCoderでのレーティングについて
AtCoderではレーティングのシステムが採用されていて、400ポイントごとにレベルが色分けされています。
高いものから、赤・橙・黄・青・水・緑・茶・灰・黒、という順番になっており、レベル感について詳しくは下記の記事でまとめていただいています。AtCoder主催の高橋直大さんのブログです。AtCoder(競技プログラミング)の色・ランクと実力評価、問題例
競プロでたまに見る「標準入力」とは
その言語で想定される一般的な入力方法。入出力といえばキーボード入力・モニタ出力なども一般的ですが、競プロにおいてはテキストファイルまたは特定の値を保持したと仮定する変数、が入力の対象となることが多い印象です。
PHPの場合、変数からの入力であればそのまま使用できますが、テキストファイルからの入力が想定されるのであればfscanf()
やfgets()
関数で取り回しできるようになることがまず必要です。PHP マニュアル - fscanf
PHP マニュアル - fgetsローカル環境でプログラムを実行して出力を確認する際は、ローカルにあるテキストファイルを
fopen()
関数で読み取って、fgets()
関数で1行ずつ変数や配列に格納したり、echo
やreturn
で返してあげたりすることから始めると良さそうです。
「標準入力から与えられた数値の合計を計算する」という問題が与えられたとして、仮に、入力用のテキストファイルをtest.txt
、実行用のプログラムファイルをindex.php
とします。test.txt3 4 3テキストファイルの取り出したい行に改行や空白が含まれて意図しない結果が出力される場合は、
trim()
関数で空白を削除することが可能です。上記を踏まえ、ローカルでの実行内容としては以下のようなものが想定されます。
index.php<?php // test.txt を r(読み取り専用)モードで開く $file = fopen("test.txt", "r"); // fgets で1行ずつテキストファイルの中身を取り出して $line に代入 // while でテキストファイルの最後の行まで繰り返すことができる while ($line = fgets($file)) { // trim で文字列 $line の先頭および末尾にあるホワイトスペースを取り除く // テキストファイルの全内容は1行ずつ配列として $temp[] に格納される $temp[] = trim($line); }; echo $temp[0] + $temp[1] + $temp[2]; // 実行結果:10 (正解)これをAtCoderなどのサイトで送信する場合は、ローカルでの入力は必要ないので、
fopen()
は削除してfgets($file)
の代わりにfgets(STDIN)
などとすれば問題なさそうです。STDINはスタンダート・インプットの略で、ソースは更に短く、下記のようになります。index.php(提出用)<?php while ($line = fgets(STDIN)) { $temp[] = trim($line); }; echo $temp[0] + $temp[1] + $temp[2];サイトによっては
echo
ではなくreturn
で返す場合もあるかと思います。
また、プログラムの書き方は1通りではないので、もっと短く効率的に書けるようであればそちらを優先してください。(例えば、配列の数値の合計を出す関数を使うともっとスマートに書けるかも、とか。)今日はいったんここまでにしておきます。
参考URL
標準入力、標準出力とは何か?
http://www.creatology.jp/unix/outin.html#err
競技プログラミングとは?メリットや初心者にもおすすめな理由も解説
https://tech-camp.in/note/technology/43369/
【PHP】複数文字列の置換(str_replace)
https://qiita.com/kazu56/items/35c10fdd79393686b26d
Paizaで使える標準入力の取得
https://qiita.com/one-kelvin/items/09068b8971c4da509cd3
PHPで標準入力から値を取得して表示する方法を解説
https://qiita.com/yuhei_umeda/items/552c3f2f19e55f80fdfb
AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~
https://qiita.com/drken/items/fd4e5e3630d0f5859067#3-hello-world-----practice-contest-a-問題のみ
AtCoder用語集
https://atcoder.jp/contests/abc074/glossary?lang=ja
PHPの出力で文字を改行(\n)させるには’’(シングルコーテーション)じゃなくて""(ダブルコーテーション)で記述する
https://qiita.com/sola-msr/items/0814c4470dcbbd1f5ec3
asort(PHP 4, PHP 5, PHP 7) — 連想キーと要素との関係を維持しつつ配列をソートする
https://www.php.net/manual/ja/function.asort.php
配列のソート
https://www.php.net/manual/ja/array.sorting.php
PHPで割り算の余り、切り上げ、切り捨て、四捨五入する方法
https://www.flatflag.nir87.com/division-414
代数演算子
https://www.php.net/manual/ja/language.operators.arithmetic.php