Language detail: HSP
Coverage: 22.84%
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- 文字列で+を表示する (Nested Flatten)
- 年賀はがきの当せん番号 (Nested Flatten)
- 箱詰めパズルの判定 (Nested Flatten)
- 関数やメソッドのソースの平均行数 (Nested Flatten)
- コレクションの実装 (Nested Flatten)
codes
シードを固定した乱数
(Nested
Flatten)
組み込みの機能で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #const CONST_SEED 32
*main
dim pt, 2, 2
repeat
gosub *LResetPoint
gosub *LRedraw
wait 120
loop
stop
*LResetPoint
dim pt, 2, 2
// 座標4点は固定シード
randomize CONST_SEED
repeat length2(pt)
pt(0, cnt) = rnd(640), rnd(480)
loop
return
*LRedraw
redraw 2
color : boxf
// 色は適当シード => 毎回変化する
randomize
color rnd(256), rnd(256), rnd(256)
boxf pt(0, 0), pt(1, 0), pt(0, 1), pt(1, 1)
redraw
return
|
出力の一時停止と再開
(Nested
Flatten)
仕様を満たしていませんでしたので、*LOnKey のルーチンを訂正いたします。
1 2 3 4 5 6 7 | *LOnKey
if ( iparam == 'P' ) {
bOutput = ( bOutput == false )
} else : if ( iparam == 'Q' ) {
end
}
return
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #ifndef __UserDefHeader__
#define true 1
#define false 0
#endif
*main
bOutput = true // 出力するかどうか
onkey gosub *LOnKey
goto *mainlp
*mainlp
if ( bOutput ) {
print "a"
}
wait 100
goto *mainlp
*LOnKey
if ( iparam == 'Q' ) {
bOutput = ( bOutput == false )
}
return
|
急勾配の判定
(Nested
Flatten)
後ろから反復してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #module
#define true 1
#define false 0
#defcfunc IsSteepSlope array arr, \
local size, local nowSum, local bResult
size = length(arr)
nowSum = 0
bResult = true
repeat size, 1
if ( cnt == 1 || nowSum < arr(size - cnt) ) {
nowSum += arr(size - cnt)
} else {
bResult = false
break
}
loop
return bResult
#global
list = 128, 64, 32, 16, 8, 4
mes IsSteepSlope(list)
stop
|
倍数になる13進数
(Nested
Flatten)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #ifndef powf
#include "hspmath.as"
#define global pow powf
#endif
#module
#define ctype cwhich_int(%1,%2,%3) \
( ((%2) * ((%1) != 0)) || ((%3) * ((%1) == 0)) )
//------------------------------------------------
// 数字列を10進数値に変換する
//------------------------------------------------
#defcfunc ChangeRadix_toDigit str _sInput, int fromRadix, \
local sInput, local result
if ( fromRadix <= 0 ) { return 0 }
sInput = getpath(_sInput, 16)
len = strlen(sInput)
result = 0
repeat len
c = peek(sInput, len - (cnt + 1))
n = cwhich_int(c >= 'a', c - 'a' + 10, c - '0')
result += n * int(powf(fromRadix, cnt))
loop
return result
#global
*main
// 総当たりで解く
repeat , 10
snum = str(cnt)
numOf13rdx = int( ChangeRadix_toDigit(snum, 13) )
numOf10rdx = cnt
if ( numOf13rdx \ numOf10rdx == 0 ) {
x = cnt
break
}
loop
dialog "A. x = "+ x
end
|
コマンドライン引数の取得
(Nested
Flatten)
コマンドライン文字列は dir_cmdline で得られるので、配列変数に格納・羅列する所まで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | // No.118 : コマンドライン文字列を取得する
#module mod_lexCmdline
#define true 1
#define false 0
#define success 1
#define failure 0
//------------------------------------------------
// コマンドライン文字列を解析し、分解する
//------------------------------------------------
#define global LexCmdline(%1=cmdopt@,%2=-1,%3=dir_cmdline) \
_LexCmdline %1,%2,%3
#deffunc _LexCmdline array cmdopt, int cntMax, str _cmdline, \
local cmdline, local index, local c,\
local bInQuote, local cQuote, local cntOpt, \
local lenOpt, local iOptBegin
if ( cntMax < 0 ) {
sdim cmdopt, 320, 10
} else {
sdim cmdopt, 320, cntMax
}
if ( cntMax == 0 ) { return }
cmdline = _cmdline
index = 0
bInQuote = false
cQuote = 0
cntOpt = 0
lenOpt = 0
iOptBegin = -1
// 分解処理
repeat
c = peek(cmdline, index)
// 終端文字
if ( c == 0 ) {
if ( lenOpt > 0 ) { gosub *LGetOption }
break
// 引用符発見 ( 引用符は cmdopt に含めない )
} else : if ( c == '\'' || c == '"' ) {
// 引用符の開始
if ( bInQuote == false ) {
if ( iOptBegin < 0 ) { iOptBegin = index + 1 }
bInQuote = true
cQuote = c
// 引用符の終了
} else : if ( cQuote == c ) {
bInQuote = false
cQuote = 0
gosub *LGetOption
if ( stat == failure ) { break }
// 関係ない文字
} else {
lenOpt ++
}
// 引用符外の空白発見
} else : if ( c == ' ' && bInQuote == false ) {
if ( lenOpt ) {
gosub *LGetOption
if ( stat == failure ) { break }
} else {
/* ignore */
}
// その他の文字
} else {
if ( iOptBegin < 0 ) { iOptBegin = index }
lenOpt ++
}
index ++
loop
return cntOpt
*LGetOption
cmdopt( cntOpt ) = strmid( cmdline, iOptBegin, lenOpt )
cntOpt ++
lenOpt = 0
iOptBegin = -1
if ( cntMax > 0 && cntOpt == cntMax ) {
return failure
}
return success
#global
LexCmdline //,, "a b c d"
repeat stat
mes strf("(%2d) ", cnt) + cmdopt(cnt)
loop
stop
|
設定ファイルから値を取得
(Nested
Flatten)
INIファイルを使い、ローマ字を漢字に変換します (林檎、葡萄、蜜柑に対応)。 作成と削除もスクリプト側が行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #uselib "kernel32.dll"
#func global WritePrivateProfileString "WritePrivateProfileStringA" sptr,sptr,sptr,sptr
#func global GetPrivateProfileString "GetPrivateProfileStringA" sptr,sptr,sptr,int,int,sptr
#define global SetIniName(%1) sdim INIPATH, 260 : INIPATH = str(%1)
#define global INIPATH _ininame@
#define global WriteIni(%1,%2,%3,%4=INIPATH) WritePrivateProfileString %1,%2,str(%3),%4
#define global WriteStrIni(%1,%2,%3,%4=INIPATH) WriteIni %1,%2,"\""+ (%3) +"\"",%4
#define global WriteIntIni WriteIni
#define global GetIni(%1,%2,%3,%4=64,%5="",%6=INIPATH) GetPrivateProfileString %1,%2,str(%5),varptr(%3),%4,%6
#module
#deffunc __ClearnUp onexit
gosub *LDestroyTestIniFile@
return
#global
#runtime "hsp3cl"
SetIniName dir_mydoc +"\\_____test_____.ini"
sdim sResult
sdim sInput, 321
gosub *LCreateTestIniFile
goto *LMainLoop
*LMainLoop
input sInput, 320, 1
getstr sInput, sInput // 改行を払う
if ( sInput == "exit" ) { end : end }
gosub *LToKanji
print sResult
wait 10
goto *LMainLoop
*LToKanji
GetIni "KanjiFromAlphabet", sInput, sResult, 320 - 1, "I don't know."
return
*LCreateTestIniFile
sData = {"
[KanjiFromAlphabet]
ringo=\"林檎\"
mikan=\"蜜柑\"
budou=\"葡萄\"
"}
notesel sData
notesave INIPATH
noteunsel
return
*LDestroyTestIniFile
exist INIPATH
if ( strsize >= 0 ) {
delete INIPATH
}
return
|
環境変数の取得
(Nested
Flatten)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #include "mod_getenv.as"
#define IDW_MAIN 0
#define true 1
#define false 0
gosub *LInitialize
gsel IDW_MAIN, 1
*LMainLoop
gosub *LGetEnvarData
gosub *LRedraw
wait 8
goto *LMainLoop
*LInitialize
gosub *LSetVariable
gosub *LSetWindow
return
*LSetVariable
sdim sData
sdim sEnvarName
sdim sResult
dim bNoExists, 2
bChanged = true
return
*LSetWindow
screen IDW_MAIN, 320, 240, 2
title "EnvarReader"
objmode 2
pos 10, 10 : mes "環境変数の名前を入力してください:"
pos 30, 30 : input sEnvarName, 200, 25
pos 10, 60 : mesbox sResult, 300, 170 : infResult = objinfo(stat, 2), stat
return
*LGetEnvarData
getenv sData, sEnvarName
bNoExists(1) = bNoExists(0)
bNoExists(0) = ( sData == "" )
if ( bNoExists(0) != bNoExists(1) ) {
bChanged = true
if ( bNoExists(0) ) {
sResult = "( なし )"
} else {
sResult = sData
}
}
return
*LRedraw
if ( bChanged == false ) { return }
objenable infResult(1), bNoExists(0) == false
objprm infResult(1), sResult
bChanged = false
return
|
LL Golf Hole 5 - 最上位の桁を数え上げる
(Nested
Flatten)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #module
#deffunc CountUpMaxPlace var vIo, local c
c = peek(vIo)
if ( '0' <= c && c <= '8' ) {
poke vIo, , c + 1
} else : if ( c == '9' ) {
poke vIo,, '1'
vIo += "0"
} else {
vIo = "0"
}
return
#global
nMax = 300 // 数える最大値
sdim sBuf, 3200
sdim sNumber
repeat
CountUpMaxPlace sNumber
sBuf += sNumber +"\n"
if ( int(sNumber) >= nMax ) {
break
}
loop
objmode 2
mesbox sBuf, ginfo(12), ginfo(13)
stop
|
LL Golf Hole 6 - 10進数を2進数に基数変換する
(Nested
Flatten)
明らかに題意とは違いますけれど、短くということで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #module
#defcfunc DigitToBinary int p1, local sRet, local c
sdim sRet, 64
repeat 32
poke sRet, 31 - cnt, '0' + (( p1 & (1 << cnt) ) != 0)
loop
return sRet
#global
mes DigitToBinary(0x80000000)
mes DigitToBinary(1234567890)
stop
|
LL Golf Hole 8 - 横向きのピラミッドを作る
(Nested
Flatten)
stop -> end でさらに1byte削れます。 最後の } もいらなかったりします (たぶんバグですが)。
1 2 | #runtime"hsp3cl"
input s,9,1:n+s:m=1:if$<=n{*@:s="":repeat i+1:s+"*":loop:mes s:i+m:if i=n{m-2}if$>i{stop}goto*@b}
|
バイナリクロック
(Nested
Flatten)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #uselib "user32.dll"
#func PostMessage "PostMessageA" int,int,int,sptr
#cfunc GetWindowLong "GetWindowLongA" int,int
#func SetWindowLong "SetWindowLongA" int,int,int
#undef BITNUM
#define global ctype BITNUM(%1) (1 << (%1))
#define WIN_HEIGHT 30
#define CELLSIZE 10
#define CX_MARGIN 1
#define CY_MARGIN 1
cx = 60 + CX_MARGIN * 2
cy = WIN_HEIGHT + CY_MARGIN * 2
bgscr IDW_MAIN, cx, cy, 2
SetWindowLong hwnd, -20, ( GetWindowLong(hwnd, -20) | 0x80 )
gsel IDW_MAIN, 2
onclick gosub *OnMove
onkey gosub *OnKeyProc
goto *mainlp
*mainlp
gosub *LCalcData
gosub *LRedraw
await 10
goto *mainlp
*LCalcData
nTime = gettime(4), gettime(5), gettime(6)
return
*LRedraw
redraw 2
color 192, 192, 192 : boxf
color
px1 = CX_MARGIN - 1
py1 = CY_MARGIN - 1
px2 = ginfo(12) - CX_MARGIN
py2 = ginfo(13) - CY_MARGIN
boxf px1, py1, px2, py2
foreach nTime
h = (192 / length(nTime)) * cnt
for i, 0, 6
if ( nTime(cnt) & BITNUM(5 - i) ) {
s = 255 - ((255 / 10) * i)
v = 255 - ((255 / 10) * i)
hsvcolor h, s, v
} else {
color 255, 255, 255
}
px1 = CX_MARGIN + ( i * CELLSIZE)
py1 = CY_MARGIN + (cnt * CELLSIZE)
px2 = CX_MARGIN + (( i + 1) * CELLSIZE) - 2
py2 = CY_MARGIN + ((cnt + 1) * CELLSIZE) - 2
boxf px1, py1, px2, py2
next
loop
redraw 1
return
*OnMove
if ( wparam == 1 ) {
sendmsg hwnd, 0x00A1, 2, 0
}
return
*OnKeyProc
if ( iparam == 27 ) { // [Esc]
gosub *LQuit
}
return
*LQuit
PostMessage hwnd, 0x0010, 0, 0
return
|
起動オプションの解析
(Nested
Flatten)
自分なら d と 数字 の間のスペースなんて許可しませんけれど。
エラー時の処理は手抜きです。 d と 数字の間にスペースがあるときの対策も手抜きです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | #module mod_LexCmdline
#define true 1
#define false 0
#define success 1
#define failure 0
//------------------------------------------------
// コマンドライン文字列を解析し、分解する
//------------------------------------------------
#define global LexCmdline(%1=cmdopt@,%2=-1,%3=dir_cmdline) _LexCmdline %1,%2,%3
#deffunc _LexCmdline array cmdopt, int cntMax, str _cmdline, local cmdline, local index, local c, local bInQuote, local cQuote, local cntOpt, local lenOpt, local iOptBegin
if ( cntMax < 0 ) {
sdim cmdopt, 320, 10
} else {
sdim cmdopt, 320, cntMax
}
if ( cntMax == 0 ) { return }
cmdline = _cmdline
index = 0
bInQuote = false
cQuote = 0
cntOpt = 0
lenOpt = 0
iOptBegin = -1
// 分解処理
repeat
c = peek(cmdline, index)
// 終端文字
if ( c == 0 ) {
if ( lenOpt ) {
gosub *LGetOption
}
break
// 引用符発見 ( 引用符は cmdopt に含めない )
} else : if ( c == '\'' || c == '"' ) {
if ( bInQuote == false ) { // 引用符の開始
if ( iOptBegin < 0 ) { iOptBegin = index + 1 }
bInQuote = true
cQuote = c
} else : if ( cQuote == c ) { // 引用符の終了
bInQuote = false
cQuote = 0
gosub *LGetOption
if ( stat == failure ) { break }
} else { // 関係ない文字
lenOpt ++
/* */
}
// 引用符外の空白発見
} else : if ( c == ' ' && bInQuote == false ) {
if ( lenOpt ) {
gosub *LGetOption
if ( stat == failure ) { break }
} else {
/* 無視 */
}
// その他の文字
} else {
if ( iOptBegin < 0 ) { iOptBegin = index }
lenOpt ++
}
index ++
loop
return cntOpt
*LGetOption
cmdopt( cntOpt ) = strmid( cmdline, iOptBegin, lenOpt )
cntOpt ++
lenOpt = 0
iOptBegin = -1
if ( cntMax > 0 && cntOpt == cntMax ) {
return failure
}
return success
#global
// こっからメイン
#define PutError(%1) dialog %1 : end 1 : end 1 // 手抜き実装
cmdline = dir_cmdline
sBool = "OFF", "ON"
sdim log
notesel log
gosub *LProcCmdline
noteadd "---- boot-log ----"
noteadd "cmdline: "+ cmdline
noteadd "[Option Info]"
if ( bOpt_o == false || cntOptStr == 0 ) {
PutError "[Error] コマンドラインに不備があります。"
}
noteadd "o: "+ sBool(bOpt_o)
noteadd "q: "+ sBool(bOpt_q)
noteadd "d: "+ nOpt_d
noteadd ""
noteadd "[Arguments Info]"
noteadd "Count: "+ cntOptStr
foreach optStr
noteadd "#"+ cnt +": "+ optStr(cnt)
loop
noteadd "---- End of Boot Log ----"
noteunsel
objmode 2
mesbox log, ginfo(12), ginfo(13)
stop
*LProcCmdline
// コマンドライン解析
LexCmdline cmdopt, , cmdline
sdim optStr, , 1
cntOptStr = 0
bOpt_o = false
bOpt_q = false
nOpt_d = -1
foreach cmdopt
dup sOpt, cmdopt(cnt)
c = peek( cmdopt(cnt) )
if ( c == 0 ) { continue }
if ( bNext_DCommand ) {
bNext_DCommand = false
if ( '0' <= c && c <= '2' ) {
nOpt_d = c - '0'
} else {
PutError "コマンドライン・エラー"
}
continue
}
switch ( c )
// 文字引数
case '+':
case '-':
case '/':
repeat strlen(sOpt) - 1, 1
c = peek( sOpt, cnt )
switch ( c )
case 'o': bOpt_o = true : swbreak
case 'q': bOpt_q = true : swbreak
case 'd':
c2 = peek( sOpt, cnt + 1 )
if ( '0' <= c2 && c2 <= '2' ) {
nOpt_d = c2 - '0'
} else {
bNext_DCommand = true
}
continue cnt + 2
swbreak
swend
loop
swbreak
// 文字列引数
default:
optStr(cntOptStr) = cmdopt(cnt)
cntOptStr ++
swbreak
swend
loop
return
|
ナベアツ算
(Nested
Flatten)
とりあえず、
「x の倍数か x のつく数 ( 0 < x < 10, x は自然数 )」
をナベアツ数といい、この x をナベアツ法数と呼ぶことにしました。
「x の倍数か x のつく数 ( 0 < x < 10, x は自然数 )」
をナベアツ数といい、この x をナベアツ法数と呼ぶことにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #module mod_nbnumber
#define true 1
#define false 0
// number が nLaw に対するナベアツ数かどうかを調べる
#defcfunc IsNabeatsuNumber int number, int nLaw, local powval
if ( nLaw <= 0 || nLaw >= 10 || number == 0 && nLaw != 0 ) {
return false
}
if ( (number \ nLaw) == 0 ) { return true } // 倍数か?
if ( (number \ 10) == nLaw ) { return true } // 1 桁目は nLaw か?
// 2桁目以降が nLaw か?
powval = 1
while ( number > powval )
powval *= 10
if ( (number / powval) == nLaw ) { return true } // i 桁目は nLaw か?
wend
return false
#global
#const MAX_VALUE 40
aho = "アホ"
finder = "人を探してる感じ"
narcist = "ナルシスト"
sdim buf, 3200
notesel buf
repeat MAX_VALUE, 1
stmp = ""+ cnt +": "
bool = 0
// アホになる
if ( IsNabeatsuNumber( cnt, 3 ) ) {
stmp += aho
bool = 1
}
// 人を探してる感じになる
if ( cnt \ 8 == 0 ) {
if ( bool ) { stmp += "&" }
stmp += finder
bool = 1
}
// ナルシスト
if ( cnt \ 5 == 0 ) {
if ( bool ) { stmp += "&" }
stmp += narcist
bool = 1
}
noteadd stmp
loop
noteunsel
mesbox buf, ginfo(12), ginfo(13)
stop
|
16進数から10進数の変換
(Nested
Flatten)
文字列処理でごり押し。
速度の最適化はしていません。
理論上は無限桁の整数に対応していますが、メモリ・時間の誓約を加味すると……?
わたしのラップトップでは 150 桁まで確認できました。( *LOmake を使用 )
速度の最適化はしていません。
理論上は無限桁の整数に対応していますが、メモリ・時間の誓約を加味すると……?
わたしのラップトップでは 150 桁まで確認できました。( *LOmake を使用 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | // ※負数は扱えない
// ※HSP3.2b2 のみ対応( strf, strtrim )
#module StrCalclator
#define true 1
#define false 0
#define ctype numrg(%1,%2,%3) \
( ((%2) <= (%1)) && ((%1) <= (%3)) )
//------------------------------------------------
// 数字 → 数値
//------------------------------------------------
#defcfunc charToNumber int chr
if ( numrg(chr, '0', '9') ) {
return chr - '0'
} else : if ( numrg(chr, 'a', 'z') ) {
return chr - 'a' + 10
} else : if ( numrg(chr, 'A', 'Z') ) {
return chr - 'A' + 10
}
return 0
//------------------------------------------------
// 数値 → 数字
//------------------------------------------------
#defcfunc numberToChar int n
if ( numrg(n, 0, 9) ) {
return n + '0'
} else : if ( numrg(n, 10, 36) ) {
return n + 'A'
} else {
return ' '
}
//------------------------------------------------
// 桁を大きい方にそろえる
//
// @ 足りない分は左側に0で詰めます
//------------------------------------------------
#deffunc Str_toSamePlaces var p1, var p2, local len, local sResult
len = strlen(p1), strlen(p2)
if ( len(0) == len(1) ) {
} else : if ( len(0) > len(1) ) {
p2 = strf("%0"+ len(0) +"s", p2)
len(1) = len(0)
} else {
p1 = strf("%0"+ len(1) +"s", p1)
len(0) = len(1)
}
return len(0)
//------------------------------------------------
// 文字列同士の加法
//------------------------------------------------
#defcfunc StrCalc_add str p1, str p2, \
local sLeft, local sRight, local sResult, \
local cntRoundUp, local places, local n, local c
sLeft = p1
sRight = p2
cntRoundUp = 0 // 繰り上がり (適当英単語)
// 桁を大きい方にそろえる
Str_toSamePlaces sLeft, sRight
places = stat
sdim sResult, places + 1
// 桁ごとの足し算
for i, places - 1, -1, -1 // 後ろの桁からの減数ループ
// 桁の数値を得る
c(0) = peek(sLeft, i)
c(1) = peek(sRight, i)
n(0) = charToNumber(c(0))
n(1) = charToNumber(c(1))
// 繰り上がりを考慮して足し算する
n(2) = n(0) + n(1) + cntRoundUp
cntRoundUp = 0
// 繰り上がり?
if ( n(2) >= 10 ) {
cntRoundUp ++
n(2) -= 10
}
c(2) = numberToChar(n(2))
// 結果に書き込む
poke sResult, i, c(2)
next
// 最後の繰り上がり
if ( cntRoundUp ) {
sResult = strf("%c", numberToChar(cntRoundUp)) + sResult
}
return sResult
//------------------------------------------------
// 文字列同士の乗法
//------------------------------------------------
#defcfunc StrCalc_mul str p1, str p2, \
local sLeft, local sRight, local sMiddle, local sResult, \
local cntRoundUp, local places, local n, local c
sLeft = p1
sRight = p2
places = strlen(sLeft), strlen(sRight)
sdim sResult, places * 2
sdim sMiddle, places + 1, places // 途中式
// 右辺の桁ごとにループ
repeat places(1)
c(1) = peek(sRight, places(1) - cnt - 1)
n(1) = charToNumber(c(1))
if ( n(1) == 0 ) {
sMiddle(cnt) = "0"
continue
}
cntRoundUp = 0 // 繰り上がり (適当英単語)
// 桁ごとのかけ算
for i, places(0) - 1, -1, -1 // 後ろの桁からの減数ループ
// 桁の数値を得る
c(0) = peek(sLeft, i)
n(0) = charToNumber(c(0))
// 繰り上がりを考慮してかけ算する
n(2) = n(0) * n(1) + cntRoundUp
cntRoundUp = 0
repeat
if ( n(2) >= 10 ) {
cntRoundUp ++
n(2) -= 10
} else {
break
}
loop
c(2) = numberToChar(n(2))
// 途中式に書き込む
poke sMiddle(cnt), i, c(2)
next
// 最後の繰り上がり
if ( cntRoundUp ) {
sMiddle(cnt) = strf("%c%s", numberToChar(cntRoundUp), sMiddle(cnt))
}
// 後ろ側に 0 を並べて桁揃え
sMiddle(cnt) += strf("%0"+ cnt +"s", "")
loop
// 途中式をすべて足し合わせる
repeat places(1)
sResult = StrCalc_add(sResult, sMiddle(cnt))
loop
return sResult
//------------------------------------------------
// 文字列の累乗
//------------------------------------------------
#defcfunc StrCalc_pow str p1, int p2, local sResult
sdim sResult
sResult = "1"
repeat p2
sResult = StrCalc_mul(sResult, p1)
loop
return sResult
//------------------------------------------------
// 10進数以外の基数の文字列を10進数文字列に変換
//
// @ 2 ~ 32 進数まで保証
// @ 負数は扱えない
//------------------------------------------------
#defcfunc StrCalc_toDigit str p1, int fromRadix, \
local sFromRadix, local sInput, local sDigit
if ( fromRadix <= 0 ) { return "" } // エラー
if ( fromRadix == 10 ) { return p1 } // 変換する必要なし
sdim sInput, 320
sdim sDigit, 320
sFromRadix = str(fromRadix)
// 小文字にする
sInput = p1
places = strlen(sInput)
// 十進数に直す
repeat places
c = peek(sInput, places - (cnt + 1))
stmp = StrCalc_mul( str( charToNumber(c) ), StrCalc_pow(sFromRadix, cnt) )
sDigit = StrCalc_add( sDigit, stmp )
loop
return sDigit
#global
*main
sLeft = "12437308CCB6", "2C9C1227FC6520B", "ff"
sResult = "20080902065334", "200904012311450123", "255"
repeat 3
mes "#"+ cnt +"\n解答:"+ StrCalc_toDigit(sLeft(cnt), 16) +"\n正答:"+ sResult(cnt)
mes
loop
stop
// おまけ
*LOmake
n = 15 // 入力する16進数の桁数の10分の1
sdim sHex, 1024
repeat n
sHex += "1234567890"
loop
sDig = StrCalc_toDigit(sHex, 16)
logmes sDig
stop
|
漢数字で九九の表
(Nested
Flatten)
せこい気がする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #define ZERO $
#define ONE length(a)
#define NINE (length(kanji) - ONE)
#define TEN length(kanji)
kanji = "○", "一", "二", "三", "四", "五", "六", "七", "八", "九"
sdim buf
buf = " "
repeat NINE, ONE
buf += " | "+ kanji(cnt)
loop
buf += "\n ―――――――――――――――――――――――――――――――――\n"
repeat NINE, ONE
x = cnt
sline = kanji(cnt)
repeat NINE, ONE
y = cnt
num = x * y
r = kanji(num \ TEN)
l = kanji(num / TEN) // 十の位
if ( l == kanji(ZERO) ) {
l = " "
}
sline += " | "+ l + r
loop
buf += " "+ sline +"\n"
loop
mes buf
stop
|
'('と')'の対応
(Nested
Flatten)
HSPのバグを使っています。( 丸括弧を使わない関数呼び出し ) Shift_JIS にのみ対応。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #const CHARCODE_LEFT 40 // '('
#const CHARCODE_RIGHT 41 // ')'
sdim buf
mesbox buf, ginfo_winx, ginfo_winy - 30
button gosub "Check!", *OnBtn_Check
stop
*OnBtn_Check
cntLeft = 0
cntRight = 0
balance = 0
bSuccess = 1
repeat
c = peek.buf.cnt
if c == 0 : break
if 0x81 <= c && c <= 0x9F || 0xE0 <= c && c <= 0xFC {
continue cnt + 2 // 全角
}
if c == CHARCODE_LEFT { cntLeft ++ : balance ++ }
if c == CHARCODE_RIGHT { cntRight ++ : balance -- }
if balance < 0 { bSuccess = 0 : break }
loop
if cntLeft != cntRight || balance != 0 : bSuccess = 0
if bSuccess {
dialog "丸括弧の対応:OK!"
} else {
dialog "丸括弧の対応:OUT!"
}
stop
|
疑似並行処理
(Nested
Flatten)
1 2 3 4 5 6 7 8 9 10 11 12 | randomize
sdim buf
cntAlph = 0
cntDig = 0
repeat 26
buf += cntDig
buf += strf("%c", 'A'+ cntAlph)
cntDig ++
cntAlph ++
loop
mes buf
|
例外処理
(Nested
Flatten)
next >>
HSPには例外処理機構が無いので、マクロで実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #define global try %tExcepHandling %i0 %i0 %i0 %i0 if (1)
#define global end_try %tExcepHandling *%p1 : %o0 %o0 %o0 %o0
#define global catch_list %tExcepHandling \
if (0) : *%p : %p3 = 0
#define global TEMP_CATCH(%1,%2) %tExcepHandling \
if ( %p3 ) { goto *%p1 } else { %p3 = 1 }\
} if (%1) { %2 = THREW_VALUE
#define global ctype catch(%1,%2=THREW_VALUE) %tExcepHandling \
TEMP_CATCH ( vartype(THREW_VALUE) == vartype("%1") ), %2
#define global ctype finally(%1=THREW_VALUE) %tExcepHandling \
TEMP_CATCH 1, %1
#define global throw(%1) %tExcepHandling \
THREW_VALUE = %1 : goto *%p
#define global try_break %tExcepHandling goto *%p1
#define global THREW_VALUE %tExcepHandling %p2
// サンプル・スクリプト
#if 1
randomize
repeat
wait 50
try {
// メイン処理、この中でしか throw できない。
switch ( rnd(3) )
case 0 : throw 2147483647 : swbreak
case 1 : throw "Hello, world!" : swbreak
case 2 : throw 3.141592 : swbreak
swend
} catch_list {
// throw されたらここに来る。
catch (int, x)
mes "int\t: "+ x
catch(str)
mes "str\t: \""+ THREW_VALUE +"\""
finally()
mes "final\t: "+ THREW_VALUE
} end_try
// catch_list を抜けるとここに来る
loop
stop
#endif
|




miso #9670() [ HSP ] Rating0/0=0.00
2時間近くソケット&HTTPと格闘していましたが、axobj使ったら3行で解決してしまいました。
axobj xml,"Msxml2.XMLHTTP" xml->"open" "POST","http://twitter.com/statuses/update.json","false","ID","パスワード" xml->"send" "status=投稿するメッセージ"Rating0/0=0.00-0+
[ reply ]