Archive for 9月, 2010

2010/09/21 指定の数字の組み合わせのすべてのパターンをリストアップ

指定の数字の組み合わせのすべてのパターンをリストアップするAppleScriptです。

あるアプリケーションでGUI側からパラメータを変更して、すべての組み合わせパターンについて総当たりで計算を行い、その計算結果をパラメータ入りのファイル名で保存したい。そんなときに、各パラメータのすべての組み合わせからなる特定桁の数のすべての組み合わせを算出……………

ああ、めんどくさい〜。考えていたらまじめに計算するのがバカバカしくなってきました。

そこで、発想の大転換。

指定桁の数値をすべて作成しておいて、ループで条件に合うものだけをピックアップすればよいのではないか、と。コンピュータのCPUパワーにモノを言わせて抽出するように路線転換してみました。

作ってみると……たしかに、プログラムは簡単。一応、チェックしてみましたが、組み合わせ数もきっちり合っています。

5つの数値パラメータから構成される数字の組み合わせを計算するために、10000〜99999までの89999個のシーケンシャル・ナンバーを作成し、パラメータの範囲を入れたリストをもとに条件にすべて合うものだけを抽出。

スクリプト名:指定の数字の組み合わせのすべてのパターンをリストアップ
set aTime to current date

set aList to {}
set aList_r to a reference to aList

set bList to {}
set bList_r to a reference to bList

set okList to {{1, 2}, {1, 2, 3}, {0, 1}, {1, 2, 3, 4}, {1, 2, 3, 4, 5, 6, 7, 8}}
set okL_r to a reference to okList

–指定桁数の数字をジェネレートする
repeat with i from 10000 to 99999
  set the end of aList_r to i
end repeat

–生成した数字リストを評価
repeat with i in aList_r
  set j to i as string
  
set cList to characters of j
  
  
set cLen to length of cList
  
set hitF to true
  
repeat with ii from 1 to cLen
    if (item ii of cList) as number is not in (item ii of okL_r) then
      set hitF to false
      
exit repeat
    end if
  end repeat
  
  
–条件にすべて合ったものだけピックアップ
  
if hitF = true then
    set the end of bList_r to contents of i
  end if
end repeat

set bTIme to current date
set cTIme to bTIme - aTime

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

結局、384個のデータを抽出。Core i7 2.66GHzのMacBook Proで7秒ほどかかりました。まあ、このぐらいで計算できたら上出来でしょう。さらにこれを4スレッドぐらいの並列処理で同時に計算したら、3秒ぐらいで終わりそうですが……

実際に処理対象の分布図を描いてみると、ほとんどが無駄な演算になってしまうので、この「無駄な演算」をどれだけ減らせるかが処理速度向上のキーポイントになります。

そこで、最上位桁にあてはまる数字に着目。ここが1つ違うだけでも1万データもかわってくるので、最上位桁だけに着目しただけでも、計算範囲を大幅に絞ることができ、大幅に処理高速化ができそうです。

ちなみに、最上位桁に入る最大の数字が2であれば…………残りの3〜9の可能性はすべて捨てて考えることができるわけで、処理対象データは89999個から19999個へと大幅に減らせます。処理対象データが80%減れば、処理速度はおのずと向上します。

実際に試してみたら、2秒で処理完了。なかなか、いい感じです。

スクリプト名:指定の数字の組み合わせのすべてのパターンをリストアップ v2
set aTime to current date

set aList to {}
set aList_r to a reference to aList

set bList to {}
set bList_r to a reference to bList

set okList to {{1, 2}, {1, 2, 3}, {0, 1}, {1, 2, 3, 4}, {1, 2, 3, 4, 5, 6, 7, 8}}
set okL_r to a reference to okList

set paramLen to length of okList

set maxDigitNum to (last item of first item of okList)

set fromNum to “1″
repeat paramLen - 1 times
  set fromNum to fromNum & “0″
end repeat
set fromNum to fromNum as number

set toNum to maxDigitNum as string
repeat paramLen - 1 times
  set toNum to toNum & “9″
end repeat
set toNum to toNum as number

–指定桁数の数字をジェネレートする
repeat with i from fromNum to toNum
  set the end of aList_r to i
end repeat

–生成した数字リストを評価
repeat with i in aList_r
  set j to i as string
  
set cList to characters of j
  
  
set cLen to length of cList
  
set hitF to true
  
repeat with ii from 1 to cLen
    if (item ii of cList) as number is not in (item ii of okL_r) then
      set hitF to false
      
exit repeat
    end if
  end repeat
  
  
–条件にすべて合ったものだけピックアップ
  
if hitF = true then
    set the end of bList_r to contents of i
  end if
end repeat

set bTIme to current date
set cTIme to bTIme - aTime

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/20 アプリケーションの状態を調べる

AppleScriptからアプリケーションの状態を調べたい、というニーズは多いようで……検索エンジンのキーワードで割と頻繁に調べられているようです。

個別のノウハウについては本Blog上で紹介していますが、体系的にノウハウを整理したことはないので、ここでまとめて紹介しておきます。

(1)アプリケーションがインストールされているかを調べる

アプリケーションの状態を調べるといっても、それがインストールされていなければ調べようがありません。最初にやるべきなのは、AppleScriptを実行するマシンにコントロール対象のアプリケーションがインストールされているかどうかを確認することです。

アプリケーションの存在確認は、Info.plistに書かれているCFBundleIdentifierを確認する必要があります。

appinfo1.jpg

Info.plistの内容確認は、Xcode Toolsをインストールすると一緒にインストールされる、「Property List Editor」で閲覧/編集が可能です。

appinfo2.jpg

Property List Editor上でキー値がそのまま表示されていない場合には、メニューの「View」から「Show Raw Keys/Values」を実行するとCFBundleIdentifierを確認できます。

appinfo4.jpg

appinfo3.jpg

このid値をもとに、Finderに対してapplicaion fileを求めると、インストールされている場合にはそのうち一番新しいバージョンのアプリケーションファイルへのaliasが得られます

(2)起動中のアプリケーションから情報を取得する

インストールされていることが確認できたら、launchなりactivateのコマンドを送って起動。そののち、起動中のアプリケーションから各種情報を取得する、というのが定石です。

たいていは、アプリケーションのプロパティを取得すれば、アプリケーションが持っている情報が得られます。ただし、ここで得られる情報はアプリケーション側のAppleScript対応度によってまちまちで、バージョン情報やアプリケーション名が分るだけ、というケースもあれば……現在選択中のオブジェクトの情報が分ったり、各種環境設定情報が分る場合もあります。

スクリプト名:アプリケーションのプロパティを取得する
tell application “iPhoto”
  properties
end tell

–> {last months album:album id 4.295966298E+9 of application “iPhoto”, selection:{album id 4.295966334E+9 of application “iPhoto”}, photo library album:album id 4.295966296E+9 of application “iPhoto”, name:”iPhoto”, version:”8.1.2″, frontmost:false, class:application, last import album:album id 4.295966297E+9 of application “iPhoto”,……(以下省略)

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

さらに、アプリケーションのプロパティを複数まとめて「properties」で取得できないアプリケーション(iTunesなど)もあるため、そういう場合にはAppleScript用語辞書をしらべて、ひとつひとつプロパティ値を取得する必要があります。

(3)System Events経由でプロセス情報を調べる

アプリケーションに対して直接問い合わせを行った場合に、環境設定情報やドキュメントの情報は取得できますが、アプリケーションプロセス自体の情報はあまり調べられません。

そこで、アプリケーション本体ではなく、System Eventsにプロセス情報を確認することになります。

スクリプト名:System Evewntsで指定IDのプロセスの状態を調べる
tell application “System Events”
  set pList to properties of first item of (every process whose bundle identifier = “com.apple.iPhoto”)
end tell
–>{enabled:missing value, unix id:46789, file:alias “Cherry:Applications:iPhoto.app:”, creator type:”iPho”, subrole:missing value, entire contents:{}, selected:missing value, application file:alias “Cherry:Applications:iPhoto.app:”, orientation:missing value, role:”AXApplication”, accepts high level events:true, file type:”APPL”, value:missing value, position:missing value, id:20128561, displayed name:”iPhoto”, name:”iPhoto”, class:application process, background only:false, frontmost:false, size:missing value, visible:true, Classic:false, role description:”アプリケーション”, maximum value:missing value, architecture:”i386″, partition space used:0, short name:”iPhoto”, focused:missing value, minimum value:missing value, help:missing value, title:”iPhoto”, accepts remote events:false, description:”アプリケーション”, total partition size:0, accessibility description:missing value, has scripting terminology:true, bundle identifier:”com.apple.iPhoto”}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

ここでは、CFBundleIdentifierによってプロセスの特定を行っていますが、Mac OS X上で気をつけるべき点があります。たとえば、Adobe Illustratorであれば……複数の異なるバージョンをインストールして、同時に複数バージョンを起動しているケースがあるということです。

そのため、厳密にアプリケーションプロセスを指定する場合には、バージョン情報なども指定する必要も出てくることでしょう。

ただし、System Eventsから取得する意義があるのは、アプリケーションが最前面にあるかどうかを示す「frontmost」、可視状態になっているかどうかを示す「visible」、そしてUNIXから見た場合のプロセスIDである「unix id」ぐらいです。

unix idを取得できれば、あとはshellのpsコマンドをdo shell scriptコマンド経由で実行し(ps -lp [process id])アプリケーションプロセスの状態を調べられます。

ここまでくれば、PhotoshopだろうがiPhotoだろうがPreviewだろうが、単なるUNIXのプロセスとして扱えます。killするなりゾンビプロセスになっていないか調べるなり、CPUへの負荷状態を調べたりできることになります。

だいたい、AppleScriptでアプリケーションプロセスの「状態」を調べるノウハウというのは、こんな感じです。

2010/09/19 openハンドラでファイルパス以外を渡す

読者の方からメールでお寄せいただいたプログラムの中に入っていて、「え? なにこれ?!」と驚いてしまったのが、このopenハンドラでファイルパス以外のものを渡すというやり方。

AppleScript Studioのアプリケーションに外部のAppleScriptから命令を渡すような場合に、コマンド入りのファイルを作成して、openハンドラ経由でそのファイルをAppleScript Studioアプリ側にオープンさせ、ファイルを経由してコントロール。

AppleScript Studioアプリケーションの内部ハンドラを外部からコントロールすることは事実上無理で、さまざまな迂回のための手段が考え出されてきましたが、ファイル経由でコマンド送信するのはなかなかいいやり方でした。……そう、処理スピードを考えなければ。

ファイルI/Oが毎回発生するので、スピードはいまひとつです。ただ、信頼性という意味では並列処理で連続して発生させても問題がなかったので、大丈夫だと考えています。

そのうえ、openハンドラをファイルI/Oを経由せずに呼び出せるのであれば、それに越したことはありません。

そんなところに飛び込んできた、openハンドラに渡せるのがファイルパスだけではないという情報。

さっそく、ためしてみました。

スクリプト名:openハンドラでファイルパス以外を渡す
set aRes to open {1, 2, 3}

on open {aFlag, bFlag, cFlag}
  display dialog aFlag as string
  
display dialog bFlag as string
  
display dialog cFlag as string
  
return true
end open

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

たしかに、openハンドラにファイルパス以外のものを渡しても大丈夫でした。ただ、openハンドラの受信パラメータに複数指定してしまうと、肝腎のファイルを(ドラッグ&ドロップで)渡したときにパラメータエラーになってしまいます。

drop1.jpg

そんなわけで、受信パラメータは1つに変更。その内容を判断して、処理するようにいろいろ試してみました。

スクリプト名:openハンドラでファイルパス以外を渡す 2
–recordをopenハンドラに渡すテスト
set aRec to {piyoID:10, piyoName:“piyopiyo”, piyoData:“ひよこさんだよ”}
set aRes to open aRec

–file aliasを単体でopenハンドラに渡すテスト
set aFile to choose file
set aRes to (open aFile)

–alias listをopenハンドラに渡すテスト
set aFol to choose folder
tell application “Finder”
  tell folder aFol
    set filesList to every file as alias list
  end tell
end tell
set aRes to open filesList

–レコード、リストに入ったaliasなどを受け付けるためのopenハンドラ
on open anObject
  set aClass to class of anObject as string
  
  
if aClass = “record” then
    set aID to piyoID of anObject
    
set aName to piyoName of anObject
    
set aData to piyoData of anObject
    
set aRes to ((aID as string) & return & aName & return & aData)
    
  else if aClass = “list” then
    –listが渡された場合
    
set bClass to (class of (first item of anObject)) as string
    
if bClass = “alias” then
      –alias listが渡されたものとして判定
      
set aRes to length of anObject –テストで長さを数えて返す。実際にはループでファイルを処理するような処理を行う
    end if
    
  else if aClass = “alias” then
    –エイリアス(ファイルパス)が単体で渡された場合。実際には、渡されたaliasのファイルをオープンしたりチェックしたりする
    
set aRes to anObject as string
    
  end if
  
  
return aRes
end open

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/12 dateに対してincMonthNumか月足した結果の年、月を取得する

dateに対して指定の月を足した結果の年、月を取得するAppleScriptです。

足す月の分だけinctementMonthルーチンをただループさせるだけですが、意外とこの手のルーチンが転がっていないために安直な方法ではありますが、作っておきました。

ただ、それほど登場頻度は高くなさそうです。

スクリプト名:dateに対してincMonthNumか月足した結果の年、月を取得する
set aDate to "2011/4/1"
set aDateObj to date aDate

set incMonthNum to 6

set dRes to addMonth(aDateObj, incMonthNum) of me

–dateに対してincMonthNumか月足した結果の年、月を取得する
on addMonth(aDateObj, incMonthNum)
  set aYear to year of aDateObj
  
set aMonth to month of aDateObj as number
  
  
repeat incMonthNum times
    set {aYear, aMonth} to incrementMonth(aYear, aMonth) of me
  end repeat
  
  
return {yearnum:aYear, monthNum:aMonth}
  
end addMonth

–カレンダー(年と月のペア)をインクリメント(+1)
on incrementMonth(aYear, aMonth)
  if aMonth < 12 then
    –1から11月の場合
    
set nMonth to aMonth + 1
    
return {aYear, nMonth}
    
  else if aMonth = 12 then
    –12月の場合
    
set nYear to aYear + 1
    
set nMonth to 1
    
return {nYear, nMonth}
    
  else
    –月パラメータが1から12の範囲になかった
    
return {false, false}
  end if
end incrementMonth

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/12 2つのdateの差を月単位で取得する。パラメータはdateオブジェクトではなくリストで

2つの日付の差を月単位で取得するAppleScriptです。

年と月をそれぞれリストで渡すと、結果がリストで返ってきます。

スクリプト名:2つのdateの差を月単位で取得する。パラメータはdateオブジェクトではなくリストで
set aDateList to {2001, 9, 1}

set bDateList to {2010, 8, 1}

set dRes to monthDiffByList(aDateList, bDateList) of me
–> {yearDiff:8, monthDiff:11}

–2つのdateの差を月単位で取得する。パラメータはdateオブジェクトではなくリストで
on monthDiffByList(aDateList, bDateList)
  set aYear to contents of item 1 of aDateList
  
set aMonth to contents of item 2 of aDateList
  
  
set bYear to contents of item 1 of bDateList
  
set bMonth to contents of item 2 of bDateList
  
  
if aMonth > bMonth then
    set dMonth to (12 - aMonth) + bMonth
    
set dYear to bYear - aYear - 1
  else
    set dMonth to (bMonth - aMonth)
    
set dYear to bYear - aYear
  end if
  
  
return {yearDiff:dYear, monthDiff:dMonth}
  
end monthDiffByList

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/08 数字で指定した月の英語名称を返す

数字で指定した月の英語名称を返すAppleScriptです。

当初、このサブルーチン内では日(day)を指定していませんでした。すると、あら不思議。日によって2月が「March」と返ってくるではありませんか!!

……あとになって、その理由を分析してびっくり。○月30日に実行(current dateを取得)してあとから月を2月に指定すると、「2月30日」を設定したことになり、繰り上がって3月になっていたのでした。

かなりマヌケなバグを作ってしまいましたが、いまとなってはいい思い出です(たぶん)。

スクリプト名:数字で指定した月の英語名称を返す
set m to getEnglishMonthName(11) of me
–> "November"

–数字で指定した月の英語名称を返す
on getEnglishMonthName(aMonth)
  set aDate to current date
  
set day of aDate to 1 –ここ、すごく重要
  
set month of aDate to aMonth
  
set mRes to month of aDate as string
  
return mRes
end getEnglishMonthName

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/05 印刷可能なプリンタ一覧から選択してプリント実行 10.4_10.6

Mac OS X 10.4用のプリント用AppleScriptが、そのままではMac OS X 10.5/10.6では使えなくなっていたので、書き換えました。

getPrintCues()ハンドラ内でlpstatコマンドの帰り値を処理しており、Mac OS X 10.5と10.6でも微妙にコマンドが返してくるメッセージが違っていたりしたので、その3つのバージョンのOSで個別の処理を行っています。

print1.jpg

なお、printコマンドで「with print dialog」と指定しているところを「without print dialog」と書き換えるとダイアログなしで印刷を実行します。

スクリプト名:印刷可能なプリンタ一覧から選択してプリント実行 10.4_10.6
–要・Mac OS X 10.5以上
set pList to getPrintCues() of me
set aPrinter to first item of (choose from list pList with prompt "出力先のプリンタを選択してください")

set aPrintSetting to {copies:1, starting page:1, ending page:1, target printer:aPrinter}

–とりあえずSafariで印刷してみた。Safariである必要はない
tell application "Safari"
  activate
  
tell document 1
    try
      print with properties aPrintSetting with print dialog –「with」を「without」にすると、ダイアログなしで印刷
    on error
      display dialog "プリント中になんかのエラーが発生しました。たぶん、キャンセルされたんでしょう" buttons {"OK"} default button 1
    end try
  end tell
end tell

(*
プロパティ:

copies integer — プリントする書類の部数
collating boolean — プリントの丁合をとるかどうか
starting page integer — 書類からプリントする最初のページ
ending page integer — 書類からプリントする最後のページ
pages across integer — 物理的なページ上に横方向に並べる論理ページの数
pages down integer — 物理的なページ上に縦方向に並べる論理ページの数
requested print time date — デスクトッププリンタが書類をプリントするべき時間
error handling standard/summarized/detailed — エラーの処理方法
fax number text — 書類の送信先ファックス番号
target printer text — 出力先のプリントキューの名前

–用紙サイズを指定できないのはどういうことなのか?(汗) 用紙サイズ指定できなかったら意味ないやんけ!
*)

–プリントキューの名称一覧を取得
–10.6用に書き換え
on getPrintCues()
  set P to paragraphs of (do shell script "lpstat -p")
  
set pList to {}
  
  
set osVer to (system attribute "sys2") as number
  
  
repeat with i in P
    set j to contents of i
    
    
if osVer = 6 then
      –10.6
      
set aPName to trimStrings(j, "プリンター ", " は待機中です。") of me
    else if osVer = 5 then
      –10.5
      
set aPName to trimStrings(j, "プリンタ ", " は待機中です。") of me
    else if osVer = 4 then
      –10.4
      
set aPName to trimStrings(j, "printer ", " is idle. enabled since ") of me
    end if
    
    
if aPName is not equal to "" then
      set the end of pList to aPName
    end if
  end repeat
  
  
return pList
end getPrintCues
–任意の文字列から指定開始子、指定終了子でトリミングした文字列を取り出す
on trimStrings(aString, fromStr, endStr)
  set fromLen to length of fromStr
  
set eLen to length of endStr
  
  
set sPos to offset of fromStr in aString
  
if sPos = 0 then return ""
  
set body1 to text (sPos + fromLen) thru -1 of aString
  
set ePos to offset of endStr in body1
  
if ePos = 0 then return ""
  
set body2 to text 1 thru (ePos - 1) of body1
  
  
return body2
end trimStrings

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/04 配置されたオブジェクトから取得した座標値を解析して、縦にいくつ並んでいるかを計算

2010/09/04 簡単な素因数分解v2

簡単な素因数分解を行うAppleScriptのバージョン2です。

バージョン1では素因数分解を行うだけでしたが、バージョン2では約数を同時に返すようにしました。

素因数分解を行っただけでは、構成要素となる素数がバラバラに取得できるだけで、約数については素因数分解を行った要素から総当たりで作る必要があり、そのあたりがちょっとお手軽に結果が得られない雰囲気。

そこで、素因数分解を行う最中に出てきた数値を別途記録しておくことで、それっぽい約数が得られて一石二鳥。

ただし、だんだん素因数分解を行うことが目的化してきたことに気付いて、あわてて本来の問題解決のためのプログラムを別途作ることに…………。

スクリプト名:簡単な素因数分解v2
set a to 64
set {b1List, b2List} to returnDivisor(a) of divisorKit
–> {{2, 2, 2, 2, 2, 2}, {32, 16, 8, 4, 2}}

–簡単な素因数分解
script divisorKit
  on returnDivisor(a)
    –1000以下の素数のリスト (prime number list under 1000)
    
set primeNum1000 to {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997}
    
    
if a > 1000 then return false –1000より大きかったらfalseをリターン(計算範囲外エラー)
    
    
if a is in primeNum1000 then
      return true –1000までの数字で、素数だった場合
    end if
    
    
–ここからメイン処理
    
set divisorList to {} –約数のリスト
    
set ansList to {} –元の数を約数で割ったときの商のリスト
    
    
repeat while a > 0
      set {r1, r2} to returnDivisorSub(a, primeNum1000) of me
      
if r1 = false then exit repeat
      
      
set the end of divisorList to r1
      
      
–計算結果リストに1が入ることを防ぐ
      
if r2 is not equal to 1 then
        set the end of ansList to r2
      end if
      
      
set a to r2
    end repeat
    
    
return {divisorList, ansList}
    
  end returnDivisor
  
  
  
on returnDivisorSub(a, primeNumList)
    repeat with i in primeNumList
      set a1 to a div i
      
set a2 to a / i
      
if a1 = a2 then
        return {contents of i, a1}
      end if
    end repeat
    
return {false, false}
  end returnDivisorSub
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/02 簡単な素因数分解

簡単な素因数分解を行うAppleScriptです。

簡単な……というのは、1000までの数に処理対象を限定しているのと、あんまりしっかり検証していないので「あ、動くからいいや」ぐらいの完成度のためです。実務で長年ビシバシにいじめまくって、これなら大丈夫……というほど裏がとれているわけでもない、というレベルです。

そもそも、なんでまた素因数分解などを作ろうと考えたかといえば、InDesign上のオブジェクトにスクリプトラベルをつける作業をしていたときに、最近こういう作業はぜんぶAppleScriptから自動で採番して実行するのですが、ラベルを付ける対象が数百個にも達し、しかもそれらが整然と並んでいるため、

 「縦に何個並んでいるか、全体の個数から勝手に判断してくれたらいいのに〜!」

などと、ふと思ってしまったからで、「じゃあ、要素数を素因数分解して、適当な候補数をchoose from listで表示してくれたらいいな〜」などと、あまり考えずに勢いだけで作りはじめたのがきっかけです(長いな)。

素因数分解などとおおげさなことを言っても、しょせんは素数で割ったリストにすぎないので、1から1000までの素数のリストを取り寄せて、割り算しながらループを回すというお気楽仕様に。思い立ってから出来上がるまで、10分ぐらい。

これで結局役に立たなくて、version 2を作る羽目になるのですが……。

スクリプト名:簡単な素因数分解
set a to 312
set b to returnDivisor(a) of divisorKit
–> {2, 2, 2, 3, 13}

–簡単な素因数分解
script divisorKit
  on returnDivisor(a)
    –1000以下の素数のリスト (prime number list under 1000)
    
set primeNum1000 to {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997}
    
    
if a > 1000 then return false –1000より大きかったらfalseをリターン(計算範囲外エラー)
    
    
if a is in primeNum1000 then
      return true –1000までの数字で、素数だった場合
    end if
    
    
–ここからメイン処理
    
set divisorList to {}
    
    
repeat while a > 0
      set {r1, r2} to returnDivisorSub(a, primeNum1000) of me
      
if r1 = false then exit repeat
      
      
set the end of divisorList to r1
      
      
set a to r2
    end repeat
    
    
return divisorList
  end returnDivisor
  
  
  
on returnDivisorSub(a, primeNumList)
    repeat with i in primeNumList
      set a1 to a div i
      
set a2 to a / i
      
if a1 = a2 then
        return {contents of i, a1}
      end if
    end repeat
    
return {false, false}
  end returnDivisorSub
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/02 iTunes 10でAppleScript用語辞書に変更なし

9/1の発表会で紹介され、その日……のうちギリギリで? ダウンロード可能になったiTunes 10。インストールして真っ先に行うのはAppleScript用語辞書が変更されているかのチェック。大規模な変更があった場合には、さまざまなプログラムを山ほど書き直さなくてはなりません。

it10_1.jpg

it10_2.jpg

HTMLに書き出して比較してみたところ、前バージョンからとくに変更点はない(0箇所)ということが分りました。

とりあえず、辞書上では変更がないということであり、挙動が変わっていないかどうかはこれからじっくり調べることになるでしょう。