くれなゐの雑記

例を上げて 自分で手を動かして学習できる入門記事を多めに書いています

天下一プログラマーコンテスト2016 予選A C問題 山田山本問題

要約

A_i < B_i, i=1,2,...,N となるように アルファベットの順番を出力する。
アルファベットの順番は辞書順最小のものを出さないといけない

やること

要約

1. AとBを左端から同じ位置にある文字を1文字ずつ比較して違うタイミングでa->bに有向グラフを張る
2. 明示的に、値が小さい方から取り出すトポロジカルソートを使用する.

  • A>B and A.size() != B.size() and グラフを貼れなかったとき: -1
  • グラフが閉路を含んでいる時: -1
  • 辺を張らなかった頂点も, 孤立した単独の頂点として取り扱う。

トポロジカルソート

有向グラフがすべて一方向を向くように、ノードを並べる。
DFSの方法とKhanのアルゴリズムがある。
トポロジカルソート - Wikipedia

memo
  • Khanのアルゴリズムを実装
  • 今回は, priority_queueでアルファベットが小さい順に取り出していく.
  • 辺の削除はコストが掛かりそうなので, 入力辺の数を数えて, 減らしていきながら数を数えた(∵それぞれの辺は一度しか使用されないため)
  • max(残りの入力辺の数) != 0 ならば, 閉路がある(-1を出力する。)

SourceCode

#include <iostream>
#include <queue>
#include <map>
#include <list>
#include <vector>
#include <string>
#include <limits>
#include <cassert>
#include <fstream>
#include <cstring>
#include <bitset>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <cstdio>
#include <ciso646>
#include <array>
#include <cmath>

using namespace std;

#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n) for (int i=0;i<(n);i++)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)

#define inf 0x3f3f3f3f
#define uinf 0x3f3f3f3f3f3f3f3f
#define CLEAR(a) a = decltype(a)()
#define MP make_pair
#define ALL(a) (a).begin(),(a).end()
#define pii pair<int ,int>
#define pcc pair<char,char>
#define pic pair<int,char>
#define pci pair<char,int>
#define VS vector<string>
#define VI vector<int>
#define VVI vector<vector<int>>
#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define pi 2*acos(0.0)
#define INFILE() freopen("in.txt","r",stdin)
#define OUTFILE() freopen("out.txt","w",stdout)
#define ll long long
#define ull unsigned long long
#define eps 1e-14
#define FIN std::ifstream cin("D:\input.txt")
const int MOD = 1e9 + 7;

// @brief topological sort (Khan's algorithm O(|V|+|E|))
// @param G[node] = {to} (G: adjacency list)
// @return sorted values (if G is closed: {})
template<class T>
vector<T> tsort(const vector<vector<T> >& G) {
	vector<T> res;
	vector<T> in(G.size());
	for (auto &node : G) for (auto &to : node) ++in[to];

	priority_queue<int, vector<int>, greater<int>> que;
	REP(i, in.size()) if (in[i] == 0) que.push(i);

	while (not que.empty()) {
		int n = que.top(); que.pop();
		res.push_back(n);
		for (auto &to : G[n]) if (--in[to] == 0) que.push(to);
	}
	return *max_element(ALL(in)) == 0 ? res : vector<T>();
}

signed int main(void) {
	int N; cin >> N;
	vector<vector<int> > G('z'-'a'+1);
	vector<bool> check('z' - 'a' + 1);
	REP(i, N) {
		string A, B; cin >> A >> B;
		int size = min(A.size(), B.size());
		bool isPush = false;
		REP(j,size) {
			if (A[j] != B[j]) {
				check[A[j] - 'a'] = true;
				check[B[j] - 'a'] = true;
				G[A[j]-'a'].push_back(B[j]-'a');
				isPush = true;
				break;
			}
		}
		if (A > B and A.size() != B.size() and (not isPush)) {
			cout << -1 << endl;
			return 0;
		}
	}

	vector<int> res = tsort<int>(G);

	if (res.size() == 0) cout << -1 << endl;

	else {
		for (auto &a : res) cout << (char)(a + 'a');
		cout << endl;
	}

	return 0;
}

ubuntuでterminalを強化したけどいろいろ躓いたメモ

Motivation

後輩がfishを使っていたので、これは便利そうだということで、そろそろterminalを強化してみようと思った
以下を参考に、強化したのだが、いろいろ躓いたところがあるのでメモを残す
各コマンドのチェックはwhichコマンドで

環境 Ubuntu16.04

qiita.com

Content

brewの代わりにaptを使用する.
oh-my-fishのリポジトリが変わっている

github.com


現在インストール方法はこう

curl -L https://github.com/oh-my-fish/oh-my-fish/raw/master/bin/install | fish
agnosterfishテーマは,
 omf install agnoster

のみで良い

powerline/fontsのリポジトリも変わってる

github.com

tmuxは一応ソースビルド

automakeとlibevent-devが必要

 sudo apt install automake
 sudo apt install libevent-dev

入ったらこれ

 git clone https://github.com/tmux/tmux
 sh autogen.sh
 ./configure && make
 sudo make install
pecoはaptじゃあ入らない
sudo apt install golang
export GOPATH=$HOME/go # .bashrcにも追加しておくこと
export PATH=$PATH:$GOROOT/bin # .bashrcにも追加しておくこと
go get github.com/peco/peco/cmd/peco
fish
omf install peco

その他functionなど参考
qiita.com

powerlineも変わってる

github.com

sudo apt install python-pip
pip install powerline-status==2.4
sudo pip psutil
zコマンドがよくわからない

kurenaif.hatenablog.com

powerlineの下にbranch名などを表示させたい

matsu.teraren.com

dotファイルはこれを参考にした
github.com

ubuntuでfish(oh-my-fish導入済み)でz

タイトル通り ubuntuでfishでzコマンドが使いたい

1. z.shを持ってきます。

 git clone https://github.com/rupa/z
 cp z/z.sh /usr/local/bin/

2. z.shのパスを指定

~/.config/fish/config.fish に 以下を追加

 set -gx Z_SCRIPT_PATH /usr/local/bin/z.sh

3. omf

 omf install z

これでfish上でzコマンドが動きます

4. z-fish (2016-10-29追記)

こいつも導入しておくひつようがあるっぽいです

`git clone`をして, `.config/fish/functions`内に`z.fish`を入れてあげる

github.com

参考文献

github.com
qiita.com

プレゼンツールメモ(主にmarkdown->pdf)

Motivation

最近、研究室に所属しプレゼンをすることが多くなりました。
以前はPowerpointを中心に使用してプレゼン発表をしていたのですが、
数式がださかったり、ソースコードの貼り付けに難があったりといろいろ問題が発生し、
markdownを使用して簡易的な進捗報告をスマートにかつスムーズに作れたらと思いいろいろ調べたのでまとめます。

使い分け

現在、以下の3つのソフトを使い分けています

1. Powerpoint
スライド プレゼンテーション ソフトウェア - Microsoft PowerPoint

2. Marp
yhatt.github.io

3. pandoc
Pandoc - About pandoc

3つとも, 現在(2016-07-14)それぞれ一長一短があります

1. powerpoint: 動画や画像の挿入が楽, 数式がダサく, ソースコードの挿入が難
2. Marp: markdownで表記できて, リアルテイムプレビュー, ソースコードの挿入が楽で画像の挿入が比較的楽, 数式がまだ未対応で、動画が不可
3. pandoc: markdownからtexに変換してpdfにするのに使用する奴, beamerな感じのスライドができる. エディタによるけど画像の挿入がめんどう. 動画は不可

texでも頑張ったら動画を挿入できるそうですが, (高専の時の)先生はそういうときはめんどうなのでpowerpoint使ってるって言ってました。

なので以下のように使い分けをします

1. powerpoint: 動画を挿入するとき。 画像の挿入が多い時
2. Marp: ソースコードやプログラミング中心の発表をするとき
3. pandoc: 数式中心で説明するとき

Marpの数式は将来的に対応するっぽいです(Githubのissueを見る限り)
現在pandocを使用しているのは数式のためなので、対応したらMarpに移行します。

markdown->pandocでスライドを作る

基本方針は, 以前の記事を参考にします。
kurenaif.hatenablog.com

デフォルトでは、日本語が対応していないらしく、このページを参考に以下のファイルを"h-luatexja.tex"という名前で保存しました。

\usepackage{luatexja}
\hypersetup{unicode=true}
\bigskip\hrule\setbeamertemplate{items}[default]

3行目は, 下のコマンドのthemeだとitem(箇条書きのやつ)がかなり見難いものになっていたので、それをデフォルトの見やすいやつに変更するコマンドです。

beamerを使用する場合, コマンドは以下のように filename.md を filename.pdf にします。

pandoc filename.md -o filename.pdf --latex-engine=lualatex -t beamer -V theme:Madrid -V colortheme:seahorse -V fontsize:12pt -H h-luatexja.tex

themeやcolorthemeをいろいろいじることはできますが, いろいろ試した結果デフォルトの中では一番これがいい感じな気がしました。

以前作ったmd2pdfも今回のスライドも, markdownからpdfという方針は変わっていないので, 同じ実行ファイルでコマンドライン引数でスライドにするか通常のA4のpdfにするかに変更できるように改造しました。


gistff3558b7210ac6c722420f76a6954ff4

これでささっと研究進捗報告ができたらいいですね

Codeforces Div.2 682C Alyona and the Tree

問題要約

ある頂点{v}から部分木の頂点{u}までの距離を{dist(v,u)}とする.
すべての{v}, {u}に対して, {dist(v,u) < a[u]}満たさないようにするために、(木の)葉を取っていく.
取った数を調べる

続きを読む

Codeforces Div.2 682D Alyona and Strings

問題要約

LCSを求めるんだけど, 連続している文字列に限りがある(っていえばいいんだろうか)
図の[]の数分しかとれないLCSみたいな

続きを読む

Python3で競技プログラミングめも

Motivation

Pythonで競技やったら早そう(小並感)と思ったのでABC039をPython3でやってみた
なれたら早そうという印象
実行時間はC++に比べて10倍程度になると思っておいて良い?
C++と比較しながらPython3でのプログラミングをメモしていく(基礎テクニックを随時更新予定)

C++との比較

入力
line = input() # そのまま入力すると文字列型になる(1行分一括)
tokens = input().split() # これでスペース区切りの文字列の配列を作る

num = int(input()) # 入力が1行に1つの数字だけだったらこれで数字
nums = list(map(int, input().split())) # これで数字のデータのスペース区切りの配列

A, B, C = list(map(int, input().split())) # こうすると3つの数字がA, B, Cの順に入る
出力
print("str") #=> "str\n"
print("str", end=" ")#=> "str "
print("str", end="")#=> "str"
print("{0} {1} {2}".format(0, "a", 2)) # フォーマット記法というらしい(まだ使ってない)
arr = [1, 2, 3, 4, 5, 6] # ただの配列宣言
print(*arr) #=> "1 2 3 4 5 6\n"
print("{:>6}".format(1)) #=>  "     1\n"
print("{:>06}".format(1)) #=> "000001\n"
print("{:>.6}".format(1)) #=> "1.000000\n"
配列(vector相当)
a = [0]*114514 # 114514のサイズを持つ配列を定義(中身は0)
arr = [] #空の配列を宣言
arr.append() #これで.push_back()相当 (型は一様でもなくても可)
2次元配列の宣言
a = [[0 for i in range(W)] for j in range(H)] # arr[H][W] = {}相当
arr = [] # 空の配列を宣言
arr.append([]) # 配列を追加することで動的に二次元配列を作ることができる
REP
for i in range(H): # REP(i,H) <=> for(int i=0;i<H;++i) 相当
 arr[i]
if(0 <= x && x < H)
if 0 <= x < H:
 arr[x]
グローバル変数的な?
def func(): #このように変数があれば引数に渡さずとも使用可能
 global S # この1行がないとたとえばS=3みたいなのを書いた時にそっちを参照されるケースがある グローバル変数を使うなら明記する
 print(S) 

S = "abc"
三項演算子
 print("OK") if True else print("NG") # (True if Boolean else False)
インクリメント
 i += 1 # i++はないです
部分配列
arr[x:y] # [x,y)な部分配列を表す(x or yは省略可 省略した場合は最初か最後を指定する感じ)
sum(arr[x:y]) # こういう使い方や
arr[1:]+arr[:1] # こうすると配列をrotateさせることができる 
std::map
dict = {} # これでC++のstd::mapっぽいことができる
dict['a'] = 3 # こんな感じで作成, アクセス可能
a == b && b == c
a == b == c
swap(a, b)
a,b = b, a
v.back()
v[-1] # 最終要素にアクセスする -2や-3も同様に後ろから

謝辞

おりさの氏とうさぎさんにいろいろおしえていただいた感謝