そんなサイトを作成して自分の実績として残したい。
まずは、体重とかを記録するだけの機能。
その後機能追加して、食事を記録したり、運動を記録したりする機能も備えたい。
需要はあるかどうか分からないが、少なくとも俺は使いたいっていうものにしたい。
とりあえず環境は整えました。
Hyper-VにセットアップしておいたUbuntuにLaravelの環境を構築。
gitリポジトリも作成しました。
詳細はこれから考える。
そんなサイトを作成して自分の実績として残したい。
まずは、体重とかを記録するだけの機能。
その後機能追加して、食事を記録したり、運動を記録したりする機能も備えたい。
需要はあるかどうか分からないが、少なくとも俺は使いたいっていうものにしたい。
とりあえず環境は整えました。
Hyper-VにセットアップしておいたUbuntuにLaravelの環境を構築。
gitリポジトリも作成しました。
詳細はこれから考える。
次はこの問題を解いてみようと思います。
これまで作成したアルゴリズムを適用してみました。
まぁ、そうだろうねぇ。
でもこれならまだ頭の中に解法はある。
次回からそれを実装していきましょう。
あ、ロード処理を少し修正しました。
最新ソースはこちら。(gitHub)
びっくりしたわ。
こういうのが届いたら、正しい物なのか調べるクセを付けておいた方がいいで。
厚生労働省のサイトを調べるとこれが見つかりました。
https://www.mhlw.go.jp/stf/newpage_03463.html
ざっくり説明すると、
過去に受け取った雇用保険料の算出方法に不正が見つかりました。
これを受け取った人は、誤って支払われた可能性があるので、内容を確認、必要事項を記入して返信してください。
少なく支払われていた場合は、その差額が口座に振り込まれます。
と、いうことなので、これは必ず返信しなければならないヤツです。
(お金がもらえる可能性があります。)
対象期間がかなりむかしなのですが、まぁ、被保険者番号が分かれば問題無いかと思います。
被保険者番号は雇用保険受給者証に記載されていますが、持っていなくても、現在所属している会社に問い合わせれば分かるみたいです。
明日投函します。
新しい遊び道具を購入しました。
LCDディスプレイです。
実際に使用するときはバックライトが白く光り、ドット単位で黒くする事ができる、らしいです。
これをラズパイで使って遊ぼうか、と。
なので、ラズパイのHATを取り外す。
そして、これとLCDディスプレイをつなぐためのケーブルを用意する。
あかんやん、オスーオスやん。
なので、これを使用する。
よく見るブレッドボードにヘッダーを取り付けました。
これを使うと、どのGPIOのピンがどこと対応しているかがすぐに分かります。
そして、本体とつなぐにはこれ。
接続。
そして、LCDディスプレイもオスが刺さるようにメスのヘッダを取り付ける。
あれ?これって、はんだづけが必要???
仕方が無い。ポチるか。
結構苦戦したので、攻略メモを残しておく。
※期間限定なので、こういうネタは寿命が短いのよね。
※そもそも、こういうネタはどれだけ需要があるか分からないし。
こちらのwikiに的の特徴が書かれていますが、
https://wikiwiki.jp/img-kirafan/極クエスト-お姉ちゃんズ11
左の赤いイノシシは魔法攻撃に弱いので、強い水のまほうつかいで簡単に倒せると思う。
問題は右の紫のイノシシで、
こちらは魔法に強いので、せんしで攻撃する必要がありますが、それでもなかなかしぶといので、アルケミストのデバフを利用するのが良いと思います。
オススメはステラの魔法の藤川歌夜(アルケミスト・水)で、
防御ダウンと行動速度低下のスキルを持っています。
あと、ナイトをパーティに含めていると、特殊攻撃を仕掛けてくるので、ナイトはパーティに含めてはならない。
デバフの後、陽属性のせんしでタコ殴りにしてスタンさせられれば勝てる。
スタンは無理でも、少ないコンテニューで勝てると思う。
ちなみにオイラは1回コンテニューで勝ちました。
攻略の参考にしてください。
前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
前回の続き。
前回は前から塗れるところをチェックしていきましたが、今回は後ろから塗れるところをチェックしていきます。
この時きちんと考えなくちゃいけないのは、データの順序。
今回、ここがぐっちゃになって一番ハマった。
前回のソースにも関連するのですが、
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
このrowlistをReverse()すると、元々の解析データ(rowNumbers)が壊れてしまうので、
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
var tempRowList = rowlist.Clone();
tempRowList.AnalyzeDatas.Reverse();
こんな感じでクローンを作成してReverse()しなくちゃいけない。
なので、クローンメソッドを追加。
class AnalyzeData
{
public AnalyzeData Clone()
{
var clone = new AnalyzeData(Value);
if (_analyzed)
{
clone.Analyzed();
}
return clone;
}
}
class AnalyzeListData
{
public AnalyzeListData Clone()
{
var clone = new AnalyzeListData();
clone.AnalyzeDatas = new List<AnalyzeData>();
foreach (var data in AnalyzeDatas)
{
clone.AnalyzeDatas.Add(data.Clone());
}
if (_analyzed)
{
clone.Analyzed();
}
return clone;
}
}
そしてパターン6の実装。
データの順番に気をつけて。
// 解析パターンその6
// 端っこ(後ろ)が塗られていたら塗る。
private void pattern6()
{
// Row
pattern6Row();
// Col
pattern6Col();
}
private void pattern6Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
var tempRowList = rowlist.Clone();
tempRowList.AnalyzeDatas.Reverse();
// 塗った場所が端っこならそこを塗る
// マスクされていない部分をリスト化して取得する
List<List<BitmapData>> data = new List<List<BitmapData>>();
{
List<BitmapData> dataList = new List<BitmapData>();
for (int col = 0; col < colNumbers.Count; col++)
{
if (_bitmapData[row, col].IsMasked() == false)
{
dataList.Add(_bitmapData[row, col]);
}
else
{
if (dataList.Count != 0)
{
data.Add(dataList);
dataList = new List<BitmapData>();
}
}
}
if (dataList.Count != 0)
{
data.Add(dataList);
}
if (data.Count == 0)
{
row++;
continue;
}
}
int rowNumberIndex = 0;
foreach (var dataList in data)
{
// 端っこが塗られているか?
dataList.Reverse();
if (dataList[0].IsPainted())
{
// すでに処理済みか?
if (tempRowList.AnalyzeDatas[rowNumberIndex].IsAnalyzed())
{
rowNumberIndex++;
if (rowNumberIndex >= tempRowList.AnalyzeDatas.Count)
{
break;
}
continue;
}
// 数字に従ってマスを塗る
int count = 0;
foreach (var s in dataList)
{
if (count < tempRowList.AnalyzeDatas[rowNumberIndex].Value)
{
s.Paint();
count++;
}
else
{
if (s.IsMasked() == false)
{
s.Mask();
}
tempRowList.AnalyzeDatas[rowNumberIndex].Analyzed();
tempRowList.CheckAnalyze();
break;
}
}
}
rowNumberIndex++;
if (rowNumberIndex >= tempRowList.AnalyzeDatas.Count)
{
break;
}
}
row++;
}
}
private void pattern6Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
// 塗った場所が端っこならそこを塗る
// マスクされていない部分をリスト化して取得する
List<List<BitmapData>> data = new List<List<BitmapData>>();
{
List<BitmapData> dataList = new List<BitmapData>();
for (int row = 0; row < rowNumbers.Count; row++)
{
if (_bitmapData[row, col].IsMasked() == false)
{
dataList.Add(_bitmapData[row, col]);
}
else
{
if (dataList.Count != 0)
{
data.Add(dataList);
dataList = new List<BitmapData>();
}
}
}
if (dataList.Count != 0)
{
data.Add(dataList);
}
if (data.Count == 0)
{
col++;
continue;
}
}
int colNumberIndex = 0;
data.Reverse();
foreach (var dataList in data)
{
// 端っこが塗られているか?
dataList.Reverse();
if (dataList[0].IsPainted())
{
// すでに処理済みか?
if (collist.AnalyzeDatas[colNumberIndex].IsAnalyzed())
{
colNumberIndex++;
if (colNumberIndex >= collist.AnalyzeDatas.Count)
{
break;
}
continue;
}
// 数字に従ってマスを塗る
int count = 0;
foreach (var s in dataList)
{
if (count < collist.AnalyzeDatas[colNumberIndex].Value)
{
s.Paint();
count++;
}
else
{
if (s.IsMasked() == false)
{
s.Mask();
}
collist.AnalyzeDatas[colNumberIndex].Analyzed();
collist.CheckAnalyze();
break;
}
}
}
colNumberIndex++;
if(colNumberIndex >= collist.AnalyzeDatas.Count)
{
break;
}
}
col++;
}
}
とりあえず、1回このロジックを当てはめてみる。
狙い通りに動いているみたいです。
なので、最後まで処理させてみる。
お、解けた。
多分、まだ完璧では無いですが、これで一歩前進です。
以前、紹介した、このマッサージ器。
これを使いまくった結果、ある事に気がついたんですよ。
オイラは以前から、あくびが止まらない、と言うことをスゴイ気にしていました。
夜になると、ホントにあくびが止まらなくて、顎が痛くなるぐらい。
しかし、そのあくびが出なくなった。
ここである事に気がついたんですよ。
首が凝る
↓
頭に巡る血流が悪くなる
↓
脳に酸素が行かなくなる
↓
脳は酸素を欲しがって、あくびをするようになる
このメカニズムが成り立つんじゃないかと。
そう考えたら、
首の凝りが解消される
↓
頭に血液が流れるようになる
↓
脳に酸素が渡るようになる
↓
あくびが止まる
いやいや、脳に酸素が行かなくなった時点でヤバイから。
でも、このマッサージ器で血流が良くなったら1万円の投資なんて安い物よ。
整体1回行ったらウン千円取られるのよ。
どちらがより経費がかからないか、なんて一目瞭然。
でも調子悪いときは一度見てもらった方が良いかもしれないけど。
いや、でもここまで激変するとは思わんかった。
これはマジで、買って良かった物ですわ。
前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
さて、今回はここを攻めていきます。
ここはマスクされたマスのすぐ隣に塗られたマスがあるので、当てはめる数字が分かればここも確実に塗ることができます。
ただ、前から塗る場合と後ろから塗る場合で、一緒に考えるとハマってしまうので、今回は前から塗るケースを考えました。
つまり、今回の対象はここになります。
解き方はこんな風に考えました。
空いているマスを抽出し、その端っこ(今回は先頭)が塗られているならば、数字に従って塗る。
そして、その次のマスは必ずマスクされますので、マスクする。
これでいきます。
// 解析パターンその5
// 端っこ(先頭)が塗られていたら塗る。
private void pattern5()
{
// Row
pattern5Row();
// Col
pattern5Col();
}
private void pattern5Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
rowlist.AnalyzeDatas.Reverse();
// 塗った場所が端っこならそこを塗る
// マスクされていない部分をリスト化して取得する
List<List<BitmapData>> data = new List<List<BitmapData>>();
{
List<BitmapData> dataList = new List<BitmapData>();
for (int col = 0; col < colNumbers.Count; col++)
{
if (_bitmapData[row, col].IsMasked() == false)
{
dataList.Add(_bitmapData[row, col]);
}
else
{
if (dataList.Count != 0)
{
data.Add(dataList);
dataList = new List<BitmapData>();
}
}
}
if (dataList.Count != 0)
{
data.Add(dataList);
}
if (data.Count == 0)
{
row++;
continue;
}
}
int rowNumberIndex = 0;
foreach (var dataList in data)
{
// 端っこが塗られているか?
if (dataList[0].IsPainted())
{
// すでに処理済みか?
if (rowlist.AnalyzeDatas[rowNumberIndex].IsAnalyzed())
{
rowNumberIndex++;
continue;
}
// 数字に従ってマスを塗る
int count = 0;
foreach (var s in dataList)
{
if (count < rowlist.AnalyzeDatas[rowNumberIndex].Value)
{
s.Paint();
count++;
}
else
{
if (s.IsMasked() == false)
{
s.Mask();
}
rowlist.AnalyzeDatas[rowNumberIndex].Analyzed();
rowlist.CheckAnalyze();
break;
}
}
}
}
row++;
}
}
private void pattern5Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
collist.AnalyzeDatas.Reverse();
// 塗った場所が端っこならそこを塗る
// マスクされていない部分をリスト化して取得する
List<List<BitmapData>> data = new List<List<BitmapData>>();
{
List<BitmapData> dataList = new List<BitmapData>();
for (int row = 0; row < rowNumbers.Count; row++)
{
if (_bitmapData[row, col].IsMasked() == false)
{
dataList.Add(_bitmapData[row, col]);
}
else
{
if (dataList.Count != 0)
{
data.Add(dataList);
dataList = new List<BitmapData>();
}
}
}
if (dataList.Count != 0)
{
data.Add(dataList);
}
if (data.Count == 0)
{
col++;
continue;
}
}
int colNumberIndex = 0;
foreach (var dataList in data)
{
// 端っこが塗られているか?
if (dataList[0].IsPainted())
{
// すでに処理済みか?
if (collist.AnalyzeDatas[colNumberIndex].IsAnalyzed())
{
colNumberIndex++;
continue;
}
// 数字に従ってマスを塗る
int count = 0;
foreach (var s in dataList)
{
if (count < collist.AnalyzeDatas[colNumberIndex].Value)
{
s.Paint();
count++;
}
else
{
if (s.IsMasked() == false)
{
s.Mask();
}
collist.AnalyzeDatas[colNumberIndex].Analyzed();
collist.CheckAnalyze();
break;
}
}
}
}
col++;
}
}
考え方は簡単に思えますが、実際に実装して見ると結構複雑になったりします。
このコーディングが正しく動かすまでに何度もデバッグを繰り返しました。
プログラミングとはそういうもんです。
基本的にトライエラーで正しく動くまで修正するのです。
実行結果はこうなりました。
小さな一歩ですが、確実に行きましょう。
前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
この問題を解いてみました。
とりあえず、前回までのロジックを実装した解析プログラムを適用してみます。
当然、解けませんでした。
では、ここに注目してみましょう。
左の数字を見ると、真ん中に4マス空いていますので、そこが塗れると思います。
逆に考えれば、その左右にある1マスの所には塗れないことが明らかになっています。
ピクロスの解析の基本は、塗れないところはマスクしていく、と言うことなので、今回の解析パターンでは、こういったスペースをマスクするロジックを作成していきます。
それができれば、残ったスペースには解析パターン2が適用されて塗ってくれるはずです。
そこで、こういうクラスを用意しました。
class Pattern4Data
{
public int Index;
public int Value;
public Pattern4Data(int index, int value)
{
Index = index;
Value = value;
}
}
空きがある位置と、空いているマスの数を数えて保持します。
これをListで持ちます。
List<Pattern4Data> countList = new List<Pattern4Data>();
こうやって、空白のある部分を全て抽出します。
その中から、与えられた数字のマスが確実に入らないところ、とりあえずは、一番小さな値よりも小さいマスを検出して、その空白を全てマスクして塗れない様にします。
と言うわけで、こういうコードを書きました。
// 解析パターンその4
// 空いているマスが少なくて塗れないマスをマスクする
private void pattern4()
{
// Row
pattern4Row();
// Col
pattern4Col();
}
private void pattern4Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
// マスクされていない連続したマスを数える
int col = 0;
int rememberCol = colNumbers.Count;
int count = 0;
List<Pattern4Data> countList = new List<Pattern4Data>();
while (col < colNumbers.Count)
{
if (_bitmapData[row, col].IsMasked() == false)
{
count++;
if(rememberCol == colNumbers.Count)
{
rememberCol = col;
}
}
else
{
if (count != 0)
{
countList.Add(new Pattern4Data(rememberCol, count));
count = 0;
rememberCol = colNumbers.Count;
}
}
col++;
if (col == colNumbers.Count)
{
if (count != 0)
{
countList.Add(new Pattern4Data(rememberCol, count));
}
}
}
// 数字の中で一番小さい値を取得する
int val = colNumbers.Count;
foreach(var s in rowlist.AnalyzeDatas)
{
if(val > s.Value)
{
val = s.Value;
}
}
// マスクされていない連続したマスの数が数字より小さい場合はマスクする
foreach(var data in countList)
{
if(val > data.Value)
{
for(int i = 0; i< data.Value; i++)
{
if(_bitmapData[row, data.Index + i].IsValid() == false)
{
_bitmapData[row, data.Index + i].Mask();
}
}
}
}
row++;
}
}
private void pattern4Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
// マスクされていない連続したマスを数える
int row = 0;
int rememberRow = rowNumbers.Count;
int count = 0;
List<Pattern4Data> countList = new List<Pattern4Data>();
while (row < rowNumbers.Count)
{
if (_bitmapData[row, col].IsMasked() == false)
{
count++;
if(rememberRow == rowNumbers.Count)
{
rememberRow = row;
}
}
else
{
if (count != 0)
{
countList.Add(new Pattern4Data(rememberRow, count));
count = 0;
rememberRow = rowNumbers.Count;
}
}
row++;
if (row == rowNumbers.Count)
{
if (count != 0)
{
countList.Add(new Pattern4Data(rememberRow, count));
}
}
}
// 数字の中で一番小さい値を取得する
int val = rowNumbers.Count;
foreach(var s in collist.AnalyzeDatas)
{
if(val > s.Value)
{
val = s.Value;
}
}
// マスクされていない連続したマスの数が数字より小さい場合はマスクする
foreach(var data in countList)
{
if(val > data.Value)
{
for(int i = 0; i< data.Value; i++)
{
if(_bitmapData[data.Index + i, col].IsValid() == false)
{
_bitmapData[data.Index + i, col].Mask();
}
}
}
}
col++;
}
}
public BitmapData[,] Run()
{
pattern1();
while (checkPainedCount())
{
pattern2();
pattern3();
pattern4();
}
return _bitmapData;
}
実行結果はこうなりました。
想定通りの動作をしていますね。