『ファイル名をわかりやすくソート』とかいう問題やろうと思ったら。


CodeIQでJavaScriptの問題でも解く練習しようと思いJavaScriptと検索してできそうな問題探してたら『ファイル名をわかりやすくソート』とか言う問題があったので挑戦しようと思いました。

が、結論から言うとコードは書き終わったけど提出できなかった。

よくよく問題を読んでみると回答を提出するには標準入力して標準出力しなければいけないみたいだが何のことだかさっぱり。

そもそもJavaScriptにもRhinoとかSpidermonkeyとか聞きなれない名前が付いてる時点で気づくべきだった。

一応気になるのでググってみるとRhinoやSpidermonkeyとはJavaScriptでコマンドライン操作やネイティブアプリを作る変態さん達用のJavaScriptのようです。

けどせっかく書いたプログラムをそっとじするのも癪なのでブログに張り付ける事にしました。

問題の内容は以下

今回は問題を簡単にするために、以下の仕様で並べ替えることにします。

  • ファイルを識別する名前は「ファイル名」と「拡張子」で構成される。例)file0123.txt
  • ファイル名部分の右端に数字がある場合は、まず右端の数字以外の部分でソートする。
  • その後、数字部分について数値としてソートする。数値として同じ場合は、さらに文字列とみてソートする。
  • 最後に、拡張子部分についてソートする。

ファイル名部分の途中に数字が入っていても、アルファベットと同じように扱うものとします。(右端の数字以外は数値とはみなさない)。
 ファイル名に使われる文字はアルファベット、数字、アンダースコアのみとし、大文字と小文字は区別するものとします。
https://codeiq.jp/challenge/2286

最初はファイル名から数字だけを抽出して文字列と数値に変換すれば良いと思ったんだがそうするとファイル名に数字が入ってる場合にそこまで抽出してしまうのでアウト。

その部分の実装に一番時間がかかり結局注釈に一番苦戦しました・・・。

で、コードがこちら。

正規表現マスターならもっとスマートに書けると思います。

最初のfor文なんか突き詰めれば1行でできそう。

ソートの部分はPHPのmultisortみたいな処理が無いのでこうするしかない。

そもそもソートの関数をアレコレ弄れば多元配列に格納せずにもできそうですが余計複雑になりそうなのでとりあえずこれで。

ちなみに処理の手順自体はすぐに思いつきましたが正規表現苦手なので想定時間の30分ではできませんでした…。


よく利用するThree.js旧バージョンからのコード書き換え(メモ)


毎回調べるのも面倒なので覚書。
色々試したくてGitHubやCodepenから他の人のコード拾ってきて弄繰り回してますが、ライブラリのバージョンが古いと一部コードに互換性が無いので、そのままでは動作しない場合があります。
バージョンアップに伴う仕様の変更はjQuery等の他のライブラリにもよくある事ですがWebGL自体まだ新しい技術なのでThree.jsは特に仕様がコロコロ変わります。
数か月前のコードをそのまま使おうとしても上手く動くことの方が稀。

ImageUtils.loadTexture

Three.jsの現行バージョンr73でもImageUtils.loadTexture(‘src’)は動きますがコンソールにもうすぐ使えなくなるという旨の注意書きがでてくるので書き換え方法

旧コード

新コード

ドキュメンテーションには.load ( url, onLoad, onProgress, onError )とあるのでロード後、ロード中、エラー時と処理を分岐できるのでもっと便利ですが、そうするとコードの構造自体書き換える必要があるのであくまで応急処置。

shadowCamera

旧バージョンではHelperを作成するのにカメラにもライトにもshadowCameraを使っていたようですが、新バージョンではそれぞれに対応するヘルパーがあるのでスポットライトに使っていたshadowCameraは使用でき代わりにSpotLightHelper(),CameraHelper()等を使います。
新しいだけあって此方の方が遥かに便利。

こちらが以前の記事『WebGLライブラリThree.jsの基礎と照明(Light)色々。』にも掲載した各種ライトのヘルパー。

See the Pen KdOVqe by Yuya Saito (@U-YA) on CodePen.

ちなみにこちらがShadowCameraで作った以前のバージョンのSpotlightのヘルパー。(by Mad Dog Tutorials)

See the Pen THREE.js Basic Scene with Spot Light by Patrick (@wpdildine) on CodePen.

今後も気づいたら色々追記していきます。


WebGLライブラリThree.jsの基礎と照明(Light)色々。


はじめに

WebGLとは
3Dモデリングの開発ソフト等に使用される3次元コンピュータグラフィックスAPIのOpenGLをJavaScriptとバインディングしてWebブラウザに適応した技術。そのまま弄るのは少し敷居が高い。
Three.js
敷居の高いWebGLを少しの3D知識とJavaScriptの知識で簡単に記述出来るようにしてくれる素敵ライブラリ。Babylon.js等他にもライブラリは沢山あるけど多分シェアと取っつき易さは1番。

バージョンアップにドキュメンテーションの更新も一部追いついていないみたいなのでドキュメンテーションを見ながらでも一部混乱した部分があったので備忘録。

  1. Three.jsの基本的な使い方
  2. ジオメトリマテリアルの種類
  3. 照明(Light)の種類

Three.jsの基礎

処理の流れ

  1. HTMLファイルの作成
  2. シーンを追加
  3. カメラの追加
  4. 物体の追加
  5. シーンのレンダリング

まずは出力するための土台となるHTMLを書きます。

各種ライブラリの読み込みとjQueryを使い慣れている人は併用も可能

続いてThree.js公式サイトから最新版のThree.js(2015/11月現在r73)をダウンロード。

ファイル内のBuildフォルダの中にThree.jsの本体があるので任意のディレクトリに移動。

examplesフォルダの中には色々なプラグインが入っているので以下の3ファイルも任意の場所に移動します。

examples->js->controls->Orbitcontrols.js
examples->js->libs->dat.gui.min.js
examples->js->libs->stats.min.js

練習用なのでbodyの中にアペンド用のdivタグが1つあればOK。

次に実際の処理。

まずScene(場面)とCamera(視点)を追加。

レンダリングするまで何を書いても出力されないので、先にレンダリング処理を行う。

ここまでの処理が最低限の土台。

ジオメトリ、マテリアルの種類

続いて物体を追加、流れは以下の通り

  1. ジオメトリ(図形)の作成
  2. マテリアル(表面)の作成
  3. 位置や回転率を設定
  4. シーンに追加

Three.jsではBlender等で作成したobjやjson,dae形式の3Dファイルの読み込みにも対応していますが、基本的なジオメトリはそのまま追加可能です。

Geometry一覧
※リンク先はドキュメンテーションでサンプルを見れます。

2D

PlaneGeometry
四角形

CircleGeometry

RingGeometry

3D

BoxGeometry
立方体

SphereGeometry
球体

TorusGeometry
トーラス(ドーナツ型)

TorusKnotGeometry
トーラス結び目

CylinderGeometry
多角柱(radiusSegmentsを増やすと実質円柱)

TetrahedronOctahedronGeometryDodecahedronGeometryIcosahedronGeometry
三角錐(三面体)、八面体、十二面体、二十面体、

TextGeometry
文字(要TextGeometry.js&フォントJSファイル読み込み)

基本的なマテリアル一覧

MeshBasicMaterial
光を一切反射しないのっぺりマテリアル

MeshPhongMaterial
光沢のあるマテリアル

MeshLambertMaterial
光沢の無い光を反射するマテリアル

3Dモデリングの基礎で使用するのは大抵この3種類。

コーディングは以下。

ここまでの処理を出力するとこんな感じ。

See the Pen MaNKmP by Yuya Saito (@U-YA) on CodePen.

照明を設定していない状態Besicマテリアルを使用すると影絵のような物体しか表示されず3Dっぽくありません。

照明の設定

続いて照明(Light)の設定を行います。

Three.jsには基本5種類の照明があります。

Ambient light
シーン全体を全方向から照らす照明です。
物理的にはほぼあり得ない照明なので照明というよりはシーン全体基本色と考えたほうが合点が行くと思います。
引数はHex(色)のみ。

Directional light
対象物の全体を1方向から照らす照明。
第一引数にはHex、第二引数にはIntensity(光の強さ)をとります。

Spot light
スポットライト。
第一引数にはHex、第二引数にはIntensity(光の強さ)、第三引数にDistance(距離)、第四引数にAngle(絞り具合)、第五引数にExponent(ターゲットの方向からの光の弱まり具合)、第六引数にDecay(拡散による光の弱まり具合)をとります。

Point light
裸電球のようにその場で全方向に拡散する照明。
第一引数にはHex、第二引数にはIntensity(光の強さ)、第三引数にDistance(距離)、第四引数にDecay(光の弱まり具合)をとります。

Hemisphere light
Point Lightと似たような特性だが上半分(skyColor)と下半分(groundColor)で別の色を設定できる照明。
第一引数にはskyColorのHex、第二引数にはgroundColorのHexをとります。

上記の通りBasicマテリアルでは光の反射は見えないのでBasic以外のマテリアルを使用。

ドキュメンテーションにも説明が掲載されていますが、読んでも実際にどう動くかわからないので色々弄ってみます。

See the Pen KdOVqe by Yuya Saito (@U-YA) on CodePen.

次はサンプルや公式ドキュメンテーションにも使用されているDAT GUIの使い方と各種Helperの使い方。


jQuery(JavaScript)でスクロールに合わせて少しずつ背景画像を動かす方法。


パララックスっぽく背景画像をの設置する方法

普通に背景画像を設置するともちろんスクロールに合わせて背景画像も動きます。

固定したい場合はbackground-attachment:fixedで固定すれば良いのですが、その中間というかスクロールに合わせて他の要素よりはゆっくりめに少しずつ動かして遠近感というかパララックスっぽい視覚効果を得たい場合の背景画像の設置方法。

まずは背景画像を設置background-attachment:fixedで配置します。
次にbackground-position-y(縦スクロールの場合)の値を%で指定します。(50%で真ん中)
あとは必要に応じてbackground-sizeやrepeatの設定を行ったらCSSの準備は完了。

pxでなく%で設定する理由は汎用性が高くレスポンシブに対応できるため。
画像や要素のサイズが決まっていればpxで指定したほうがサクサク動くかもしれません。

次にjQueryで行う事は3つ

1.Body(背景画像を設置する要素)の高さの取得
2.スクロール位置(TOP)の取得
3.以上の値からbackground-position-yの値の取得

簡単ですね。
CSS

JS

サンプルはこちら。

80/getHeight*ScrollTop+10;の部分は何をやってるのかというと中学数学レベルで難しい事は無く、動かす値(80)を最大値(getHeight)で割って1pxスクロール当たり何%動くかを計算、それにスクロール値(ScrollTop)を掛けたものに初期値(10)を足しています。

厳密にはgetHeightでは最大値+ウィンドウの高さですがこの大きさの場合誤差レベルというか入力する値で動き方を調節すれば良いだけなので無視します。
気になる人やもっと小さい要素で行う場合はwindow.innerHeightでウィンドウの高さも取得してください。
ウィンドウサイズ変更に伴う挙動も気になる人はwindow.onresizeのイベントハンドラで関数を作ってgetHeightを実行してください。

ちょっと長くなりますがこんな感じだと思います。(ちなみに上のサンプルは此方で実装してます)

画像とウィンドウの比率によっては画像が切れたりあまり動いてないように見える事があるのでそこら辺は調節してください。

最初から割と縦長の画像を使ったりリサイズ時に画像を切り替えてもいいかもしれません。

今回は下に動かしましたが、上下左右どこでも好きな方向に移動できます。(左右の場合はbackground-position-xを操作して最大値もHeightではなくWidthを取得します。)

body以外の複数にも設定することでよりパララックスな感じを出すこともできると思います。

※とりあえずやりたかった事を自分なりに実装しただけであまりちゃんと調べてないので、もっと簡単に実装できる方法もあるかもしれません。

モバイルでも使えますが端末とブラウザによってはカクカクします。

スマホでパララックスはまだ厳しいかなぁ。


jQuery MobileにGoogle Adsenseをブチ込む裏ワザ


※この内容はjQuery1.4.3に準拠します。その他のVer.では動作確認していません。

jQuery Mobile、便利ですよね。

現在、最新版は1.4.5で僕は1.4.3を利用していますが1.3.x以前のバージョンでも基本的には1枚のHTMLに複数のページ内容を記述してAjaxでコンテンツ内容を入れ替える仕組みになっているjQuery Mobile.

そして利用している人なら御存知の通りGoogle Adsenseとの相性が最悪。

全ページにGoogle Adsenseのコードを普段通り書き込んでも上から数えて最初の2,3個しか表示されません。

これはGoogle Adsenseの規約に同一ページ内に表示できる同一種類のAdsense広告は3つまでと決まっていから。

それ以上コードを書き込んでも大きなスペースが空くだけで肝心の広告は表示されません

これでは単にソースを重たくするだけで何の意味もない。

日本語、英語と色々ググってみましたが主流なやり方は2つですが、問題が色々。

jQuery MobileにGoogle Adsenseを設置する上での諸問題点と、今回紹介する3つ目の裏ワザ的な方法を紹介します。

1)jQueryのAjaxでのページ遷移をオフにする方法。

ソースに以下の一行を書き加えるだけ。

しかしこれはせっかくのjQuery Mobileの利点を消し去っているようなものです。

デフォルトでれば部分的にソースを読み込んで差し替えているだけですが、Ajaxを切るということは遷移の度に全ソースを読み込んで表示しています。

更に広告のソースも貼り付ける分だけ書き込まなければならないのでクライアントによってはモッサリ感が半端じゃない。

その他にも色々と問題があるようでそれについては下記のブログに詳しく書かれています。

そろそろjQuery Mobileでajaxを無効にしてるやつに一言いっておくか|へっぽこプログラマーの日記

2)Adsense広告をiframe内に表示する

やり方は以下のとおり。

HTML内のJS部分

jQueryソース

参照:jQueryMobileでGoogle Adsenseを使う | @thoriki

このソースはsectionタグがあるあたり1.4.3より古いバージョンみたいですが適宜書き換えましょう。

他にも英語ソースのStackOverflowjQueryのフォーラムにも似たようなソースがありました。

これは結構良さそうと思ったのですが、試していません。

なぜならGoogleのフォーラムに以下のような書き込みがありました。

Query Mobileでの作成サイトにGoogleAdsenseを張り付ける方法について

質問:
Query Mobileを使用してスマートフォン用のサイトを作成し、モバイル コンテンツ向け AdSenseコードを張り付けました。
通常の処理においては問題ないのですが、戻るボタンを押してページを表示した場合にAdsenseだけがページに表示さ
れる現象が起きます。
————中略————

確かに、iframeを利用したら当現象はおきなくなりました。
しかし、iframe内のGoogleAdsenseの利用については、「Google 広告を iframe に配置することも禁止されます。」
との記述があり、iframeを使用することに若干抵抗があります。
他に良い解決策はありませんか?またポリシー違反にならないかを教えてください。
答え:
jQuery Mobile のサイトに AdSense を表示する件について、 いかなる理由でも iframe 内に広告を埋め込むことは認められませんのでご注意ください。

というわけでこの方法、かなり浸透しているものの実は規約違反。

そこでこれらの問題を両方パスできる今回の裏ワザです。

3)HTMLタグの外側に広告を埋め込む。

jQuery遷移の度にクライアントに表示されるソースがヘッダーから丸々変わってしまうjQuery Mobile。

ならばその処理が適応される範囲外、つまり<HTML></HTML>の外側に書いてしまえば良いのではないか。

そしてその要素のpositionをfixにしてz-indexにjQM内で使われている最大値より大きな値をセットすればどの要素よりも優先的に表示されます。

ページが遷移しても広告は切り替わりません。

広告の読み込みもリロードしない限り1回きりなので3つの方法の中では読み込み速度も一番軽いと思います。

いくら遷移しても表示されている広告はそのまま。

CSSだけで表示場所も好きに移動可能です。

ソースはこちら。

まさにHTMLのルールをブチ破った型破りな裏ワザ

利点はCSSとHTMLだけでjQueryや広告のJavaScriptを改変しなくていいので凄く簡単。

この方法で設置したものがこちら。

スポーツで使えるお役立ちツール | cityJumperWEB.com

勿論W3CやAnother HTML-lint 5には思い切り弾かれるでしょうが、それが一体どれだけページ品質に悪影響を及ぼすかなんてたかが知れています。

責めるなら現状で正攻法でAdsenseが設置出来るようになっていないjQuery MobileさんかGoogle様を責めて下さい。

どの方法を選ぶかはあなた次第。

1)の方法でjQueryの利点を殺して、ユーザーに更なるモッサリ感を与えてまでAjaxを無効にする。

2)の方法で最悪Adsenseの利用を制限される可能性があるが、Google様の定めた規約を破る。

3)形骸化されたルールを無視して1)と2)の問題をパスする。

とりあえず僕は今回紹介した裏ワザ、3)の方法で設置しています。

大丈夫だと思いますがググっても同じ方法で設置している人は見つからなかったので、何か問題が起こり次第当ブログにて報告致します。

何故か表示される時とされない時(内部リンクから飛んだ時)がある問題については現在調査中。

ほっといたら直ってるのでGoogleサイドの問題かなーと思います。