2016年02月13日

シェルスクリプト(dash|bash)でパスワードを生成


#!/bin/dash
set -u
set -e

fun_main() {
fun_generate_password 16
}

# 指定した長さのパスワードを生成
fun_generate_password() {
local pass_len=$1
local src="$(fun_char_range "!" "~")"
local src_len=${#src}
local pass=""
local i
for i in $(seq ${pass_len}); do
pass="${pass}$(fun_echo "${src}" | cut -c $(fun_get_random 1 ${src_len}))"
done
fun_echo "${pass}"
}

# 指定した範囲の文字を返す
fun_char_range() {
local min=$(fun_asc "$1")
local max=$(fun_asc "$2")
local chars=""
local code
for code in $(seq ${min} ${max}); do
chars="${chars}$(fun_chr ${code})"
done
fun_echo "${chars}"
}

# 指定した範囲の乱数を返す
fun_get_random() {
local min=$1
local max=$2
local range=$((max - min + 1))
local random_count=$((1 << 56))
local cutoff=$((random_count - random_count % range))
local num
while :; do
num=$((0x$(od -A n -N 7 -t x1 /dev/urandom | sed "s/ //g")))
if [ ${num} -lt ${cutoff} ]; then
break
fi
done
fun_echo $((num % range + min))
}

# 文字コードを文字に変換
fun_chr() {
printf "\\$(printf "%o" $1)"
}

# 文字を文字コードに変換
fun_asc() {
printf "%d" "\"$1"
}

fun_echo() {
printf "%s\\n" "$1"
}

fun_main

posted by moritora at 20:55| Comment(0) | シェルスクリプト | このブログの読者になる | 更新情報をチェックする

シェルスクリプト(dash|bash)でマルチプロセスの処理


#!/bin/dash
set -u
set -e

fun_main() {
# ジョブ一覧ファイル
# 優先度順に並べておく
local jobs_file=jobs.txt
: > ${jobs_file}

local i
for i in $(seq 10); do
echo job_${i} >> ${jobs_file}
done

# 行番号ファイル
# 1で初期化
local num_file=num.txt
echo 1 > ${num_file}

# ジョブの件数
local jobs_count=$(wc -l < ${jobs_file})

# 4つのプロセスで処理
local id
for id in $(seq 4); do
# 別のプロセスで処理
while :; do
# 行番号
local num

# ファイルディスクリプタとロックファイルを
# むぎゅっと紐付け
{
# ここからブロックを抜けるまでロック
flock -x 3

# 行番号を読み込んで
# インクリメントして書き込み
num=$(tail -n 1 ${num_file})
echo $((num + 1)) >> ${num_file}
} 3>> ${num_file}.lock

# 行番号がジョブの件数を超えたらおしまい
if [ ${num} -gt ${jobs_count} ]; then
break
fi

# 行番号を指定してジョブを取得
local job=$(head -n ${num} < ${jobs_file} | tail -n 1)

# ジョブを実行
echo "${id} -> ${job}"
done &
done

# すべてのプロセスが終了するのを待機
wait
}

fun_main
posted by moritora at 17:29| Comment(0) | シェルスクリプト | このブログの読者になる | 更新情報をチェックする

2014年11月24日

サクラエディタで行をシャッフルするマクロ

んんん!シャッフル!!シャッフルー!!

Option Explicit

Function DV(A, B)
DV = Fix(A / B)
End Function

Function RD(A, B)
RD = DV(A, B) * B
End Function

Function MD(A, B)
MD = A - RD(A, B)
End Function

Function XR(A, B)
Const N = &H10000
XR = (DV(A, N) Xor DV(B, N)) * N + (MD(A, N) Xor MD(B, N))
End Function

Function SL(A, B)
SL = MD(A, 2 ^ (32 - B)) * (2 ^ B)
End Function

Function SR(A, B)
SR = DV(A, 2 ^ B)
End Function

Function Step1(Y)
Step1 = XR(Y, SL(Y, 13))
End Function

Function Step2(Y)
Step2 = XR(Y, SR(Y, 17))
End Function

Function Step3(Y)
Step3 = XR(Y, SL(Y, 5))
End Function

Function XRS(Y)
XRS = Step3(Step2(Step1(Y)))
End Function

Class Random
Dim Y

Sub Class_Initialize()
Y = 2463534242
End Sub

Function GetValue()
Y = XRS(Y)
GetValue = Y
End Function

Function InInRange(V, R)
If V < R Then
InInRange = V
Else
InInRange = InInRange(GetValue(), R)
End If
End Function

Function InRange(R)
Const X = 4294967295
InRange = MD(InInRange(GetValue(), RD(X, R)), R)
End Function

Function Range(N, X)
Range = InRange(X - N + 1) + N
End Function
End Class

Sub Swap(A, X, Y)
Dim T
T = A(X)
A(X) = A(Y)
A(Y) = T
End Sub

Sub Shuffle(A, R)
Dim I
For I = UBound(A) To LBound(A) + 1 Step -1
Swap A, I, R.Range(0, I)
Next
End Sub

Function GetLineCode()
Dim A
A = Array(vbCrLf, vbCr, vbLf)
GetLineCode = A(Editor.GetLineCode())
End Function

Sub SelectLines(LineStart, LineEnd)
Editor.Jump LineStart
Editor.BeginSelect
Editor.Jump LineEnd
Editor.GoLineEnd
Editor.BeginSelect
End Sub

Sub Main()
Dim LineFrom
LineFrom = Editor.GetSelectLineFrom()

Dim LineTo
LineTo = Editor.GetSelectLineTo()

If Editor.GetSelectColmTo() = 1 Then
SelectLines LineFrom, LineTo - 1
Else
SelectLines LineFrom, LineTo
End If

Dim Text
Text = Editor.GetSelectedString(0)
Text = Replace(Text, vbCrLf, vbLf)
Text = Replace(Text, vbCr, vbLf)

Dim A
A = Split(Text, vbLf)
Shuffle A, New Random

Editor.InsText Join(A, GetLineCode())
SelectLines LineFrom, LineTo
End Sub

Main
posted by moritora at 14:19| Comment(2) | VBScript | このブログの読者になる | 更新情報をチェックする

2013年09月14日

Fontforgeでフォントの横幅を80%に縮小するPythonスクリプト。


import fontforge
import psMat

def main():
r = 0.80
f = fontforge.activeFont()

gs = []
for g in f.glyphs():
if (g.isWorthOutputting()):
gs.append(g)

ws = {}

for g in gs:
if (g.references != ()):
ws[g.glyphname] = g.width

for g in gs:
if (g.references == ()):
wr = 0.0
if (g.width > 0):
wr = bround(g.width * r) * 1.0 / g.width
else:
wr = r
g.transform(psMat.scale(wr, 1.0))
else:
shrinkReferences(g, r)
shrinkPossub(g, r)

for g in gs:
if (g.references != ()):
if (ws[g.glyphname] == g.width):
g.width = bround(g.width * r)

def shrinkPossub(g, rate):
for s in g.getPosSub("*"):
t = s[1]
if (t == "Position"):
position(g, s, rate)
elif (t == "Pair"):
pair(g, s, rate)

def shrinkReferences(g, rate):
rs = list(g.references)
for i in range(0, len(rs)):
r = rs[i]
c = list(r)
m = list(c[1])
m[4] = bround(m[4] * rate)
c[1] = tuple(m)
rs[i] = tuple(c)
rs.reverse()
g.references = tuple(rs)

def bround(n):
i = int(n)
d = n - i
if (abs(d / 0.5 - 1.0) < sys.float_info.epsilon):
if ((i & 1) == 1):
return i + 1
else:
return i
else:
if (d > 0.5):
return i + 1
else:
return i

def pair(g, s, r):
subtable = s[0]
otherGlyph = s[2]

fstXoff = bround(s[3] * r)
fstYoff = s[4]
fstXadv = bround(s[5] * r)
fstYadv = s[6]

sndXoff = bround(s[7] * r)
sndYoff = s[8]
sndXadv = bround(s[9] * r)
sndYadv = s[10]

g.addPosSub(subtable, otherGlyph,
fstXoff, fstYoff, fstXadv, fstYadv,
sndXoff, sndYoff, sndXadv, sndYadv)

def position(g, s, r):
subtable = s[0]
xoff = bround(s[2] * r)
yoff = s[3]
xadv = bround(s[4] * r)
yadv = s[5]

g.addPosSub(subtable, xoff, yoff, xadv, yadv)

main()


最初はFontforgeスクリプトでやってみたのだけれども、どうも幅が指定したとおりにならなかったり、
左右の空白の比率がおかしくなったりでPythonスクリプトを使うことにした。
posted by moritora at 22:19| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

奇偶ヒープソートを実装する。

通常のヒープーソートは次のようなバランスの取れたヒープを作成しソートを行う。


奇偶ヒープソートでは次のような左に傾いたヒープを作成しソートを行う。




Sub Swap(a, i, j)
Dim t
t = a(i)
a(i) = a(j)
a(j) = t
End Sub

Sub OddEvenHeapsort(a)
Dim i
For i = 2 To UBound(a) Step 2
Heapify a, i
Next

Dim u
If (UBound(a) And 1) = 1 Then
u = UBound(a)
Else
u = UBound(a) - 1
End If

For i = u To 1 Step -2
If a(i - 1) > a(i) Then
Swap a, i - 1, i
Heapify a, i - 1
End If
Next
End Sub

Sub Heapify(a, ByVal p)
Dim t
t = a(p)

Do While p >= 2
Dim r
r = p - 1

Dim l
l = p - 2

Dim c
If a(l) > a(r) Then
c = l
Else
c = r
End If

If t >= a(c) Then
Exit Do
End If

a(p) = a(c)
p = c

If c = r Then
Exit Do
End If
Loop

a(p) = t
End Sub
posted by moritora at 15:27| Comment(0) | VBScript | このブログの読者になる | 更新情報をチェックする

奇偶転置ソートを実装する。




Sub Swap(a, i, j)
Dim t
t = a(i)
a(i) = a(j)
a(j) = t
End Sub

Sub OddEvenSort(a)
Dim i
Dim swapped

Do
swapped = False

For i = 0 To UBound(a) - 1 Step 2
If a(i) > a(i + 1) Then
Swap a, i, i + 1
swapped = True
End If
Next

For i = 1 To UBound(a) - 1 Step 2
If a(i) > a(i + 1) Then
Swap a, i, i + 1
Swapped = True
End If
Next
Loop While swapped
End Sub

posted by moritora at 15:19| Comment(0) | VBScript | このブログの読者になる | 更新情報をチェックする

2013年09月01日

挿入ソートを実装する。



私の環境では、
要素数が8以下であれば挿入ソートが速く、
要素数が16以上128以下であればペア挿入ソートが速く
要素数が256以上であれば二分挿入ソートが速かった。

要素数が256以上になるとクイックソートやマージソートのほうが二分挿入ソートよりも速いので二分挿入ソートの使いどころがよくわからない。


Sub Insertion(a)
Dim i
For i = 1 To UBound(a)
Dim t
t = a(i)

Dim j
For j = i To 1 Step -1
If a(j - 1) <= t Then
Exit For
End If

a(j) = a(j - 1)
Next

a(j) = t
Next
End Sub


Sub PairInsertion(a)
Dim i
For i = 2 To UBound(a) Step 2
Dim min
Dim max

If a(i - 1) < a(i) Then
min = a(i - 1)
max = a(i)
Else
min = a(i)
max = a(i - 1)
End If

Dim j

For j = i To 2 Step -1
If a(j - 2) <= max Then
Exit For
End If

a(j) = a(j - 2)
Next

a(j) = max

For j = j - 1 To 1 Step -1
If a(j - 1) <= min Then
Exit For
End If

a(j) = a(j - 1)
Next

a(j) = min
Next

If UBound(a) Mod 2 = 1 Then
Dim t
t = a(UBound(a))

For i = UBound(a) To 1 Step -1
If a(i - 1) <= t Then
Exit For
End If

a(i) = a(i - 1)
Next

a(i) = t
End If
End Sub


Sub BinaryInsertion(a)
Dim i
For i = 1 To UBound(a)
Dim v
v = a(i)

Dim l
l = 0

Dim u
u = i - 1

Do While l <= u
Dim c
c = ((u - l) \ 2) + l

If v < a(c) Then
u = c - 1
Else
l = c + 1
End If
Loop

Dim j
For j = i To l + 1 Step -1
a(j) = a(j - 1)
Next

a(l) = v
Next
End Sub
posted by moritora at 19:40| Comment(0) | VBScript | このブログの読者になる | 更新情報をチェックする