iso tank - このHPのこと 2019年

さくらレンタルサーバの仕様変更

以前、さくらのレンタルサーバの仕様とblosxomの仕様の兼ね合いで若干問題が生じることについて触れた。

が、実は2017年3月に仕様変更があり、MultiViewsオプションが使用できるようになっていた。

以前書いたとおり、blosxomのカテゴリとして使用するディレクトリと同じ名前のファイルを設置すると、カテゴリに遷移した時にファイルの方の中身がぶちまけられてしまう、という問題があったが、

Options -MultiViews

と.htaccessに記述するだけで、ファイル名とディレクトリ名がカブっても問題なく動作するようになる。

以前から直っていたが、記事をそのまま放置してしまっていた。

ただし、環境変数を追加できない問題だけは解決していない。が、これは仕方ないと思うし、むしろコードの方がある程度自由に弄られることを許容してるんじゃないかな? と考えてたりもする。自分のスキル不足もある。

highlight.jsを導入してみる

別になんてこたないんだけどね。

highlightjs.orgというサイトで公開されているライブラリを使用すれば、ブログ記事とかにプログラムのコードを貼り付けると自動的にシンタックスハイライトをしてくれるらしい。

blosxomのプラグインとしてコードをシンタックスハイライトする奴を作ろうかなー、とか思ってたけど既にあったわ。という話。

というわけで、ちょっと実験。

Option Explicit

'---------------------------------------------------------------------------------------------------
' クイックソート関数(SourceArray   <配列>)
'   説明: 渡された配列の要素をクイックソート(非安定ソート)で昇順に並び替える。
'---------------------------------------------------------------------------------------------------
Public Function QuickSort(ByVal SourceArray As Variant) As Variant
    
    Dim valLEnd As Variant      '左端の値
    Dim valREnd As Variant      '右端の値
    Dim valMed As Variant       '中央値
    Dim valSwap As Variant      'バッファ(値交換用)
    Dim posLEnd As Long         '左端の位置
    Dim posREnd As Long         '右端の位置
    Dim posLEnds() As Long      '左端の位置を記憶するスタック(配列)
    Dim posREnds() As Long      '右端の位置を記憶するスタック(配列)
    Dim topStack As Long        'スタック(配列)の最大添字 ※スタック確保用
    Dim bottomStack As Long     'スタック(配列)の最小添字 ※Option Base 1 への対策用(念の為)
    Dim ptrStack As Long        'スタック(配列)のポインタ
    Dim ptrLtoR As Long         '左端から右に向かって探索するポインタ(Lポインタと呼称)
    Dim ptrRtoL As Long         '右端から左に向かって探索するポインタ(Rポインタと呼称)
    
    '初期処理
    If Not IsArray(SourceArray) Then
        Exit Function
    End If
    Let posLEnd = LBound(SourceArray)   '引数の左端の位置
    Let posREnd = UBound(SourceArray)   '引数の右端の位置
    Let bottomStack = LBound(Array())   'スタックの最小添字
    Let topStack = Int(Log(posREnd - posLEnd + 1) / Log(2)) + bottomStack  'スタックサイズはLog2(n)個で足りる
    ReDim posLEnds(topStack)            'スタック確保
    ReDim posREnds(topStack)
    Let ptrStack = bottomStack          '全体範囲をスタックにPUSH
    Let posLEnds(ptrStack) = posLEnd
    Let posREnds(ptrStack) = posREnd
    
    'メイン処理
    Do Until ptrStack < bottomStack     'すべてのスタックが処理されるまで繰り返す
        
        '探索範囲POP・値取得
        Let posLEnd = posLEnds(ptrStack)    'スタックから両端の位置を取り出す
        Let posREnd = posREnds(ptrStack)
        Let ptrLtoR = posLEnd               '両端の位置をLポインタ・Rポインタにそれぞれセット
        Let ptrRtoL = posREnd
        Let valLEnd = SourceArray(ptrLtoR)  '両端の値と中間位置の値を取得
        Let valREnd = SourceArray(ptrRtoL)
        Let valMed = SourceArray(ptrLtoR + Int((ptrRtoL - ptrLtoR) / 2))
        
        '中央値導出(左端の値・右端の値・中間位置の値、の3値から中央値を求める)
        If valLEnd > valMed Then
            If valREnd > valLEnd Then
                Let valMed = valLEnd
            ElseIf valREnd > valMed Then
                Let valMed = valREnd
            End If
        ElseIf valLEnd > valREnd Then
            Let valMed = valLEnd
        ElseIf valMed > valREnd Then
            Let valMed = valREnd
        End If
        
        '探索・値交換
        Do Until ptrLtoR > ptrRtoL          'LポインタとRポインタの位置が逆転するまで繰り返す
            Do Until SourceArray(ptrLtoR) >= valMed
                Let ptrLtoR = ptrLtoR + 1   '左から右へ、中央値以上の値の位置を探索する
            Loop
            Do Until SourceArray(ptrRtoL) <= valMed
                Let ptrRtoL = ptrRtoL - 1   '右から左へ、中央値以下の値の位置を探索する
            Loop
            If ptrLtoR > ptrRtoL Then
                Exit Do                     'LポインタとRポインタの位置が逆転したら探索・値交換を終了する
            End If
            If ptrLtoR < ptrRtoL Then       'Lポインタ<Rポインタ であれば、左の値と右の値を交換する
                Let valSwap = SourceArray(ptrLtoR)  '(左の値は中央値以上、右の値は中央値以下になっている)
                Let SourceArray(ptrLtoR) = SourceArray(ptrRtoL)
                Let SourceArray(ptrRtoL) = valSwap
            End If
            Let ptrLtoR = ptrLtoR + 1       'Lポインタ≦Rポインタ であれば、範囲を1つずつ狭める
            Let ptrRtoL = ptrRtoL - 1
        Loop
        
        '探索範囲の分割・交換(左範囲[左端~交差したRポインタ] 右範囲[交差したLポインタ~右端])
        If ptrRtoL - posLEnd < posREnd - ptrLtoR Then   '※ポインタの間に要素がある場合、その要素の位置は確定
            Let ptrLtoR = ptrLtoR Xor posLEnd   '左範囲と右範囲で、範囲の広い方を先にスタックするように調整
            Let posLEnd = ptrLtoR Xor posLEnd   '何もなければ左範囲→右範囲の順でスタックするようになっている
            Let ptrLtoR = ptrLtoR Xor posLEnd   '右範囲の方が左範囲より広ければ、左右の端の位置とポインタを交換
            Let ptrRtoL = ptrRtoL Xor posREnd   '左端←→Lポインタ、Rポインタ←→右端
            Let posREnd = ptrRtoL Xor posREnd   'スタックのサイズをLog2(n)以下に抑えられるようになる
            Let ptrRtoL = ptrRtoL Xor posREnd
        End If
        
        '探索範囲(広い方)PUSH
        If posLEnd < ptrRtoL Then               '範囲内の要素が2以上あればスタックにPUSHする
            Let posLEnds(ptrStack) = posLEnd    '(1つしかない場合はその要素の位置が確定したためPUSHしない)
            Let posREnds(ptrStack) = ptrRtoL    '現在処理中のスタックは上書きされる(実質的にPOPと同じ動作)
            Let ptrStack = ptrStack + 1         'スタックポインタに1加算=次の空きスタックへ移動
        End If
        
        '探索範囲(狭い方)PUSH
        If ptrLtoR < posREnd Then               '上記と同じ処理
            Let posLEnds(ptrStack) = ptrLtoR
            Let posREnds(ptrStack) = posREnd
            Let ptrStack = ptrStack + 1
        End If
        
        '最上位スタックへポインタ移動
        Let ptrStack = ptrStack - 1
    Loop
    Let QuickSort = SourceArray
End Function

コードは前に何かで使ったクイックソート。さて、どうかな?