今後の記事は全て Qiita に投稿します。
以前の記事はこのまま置いておきます。今後は↓こちらへどうぞ
コラッツの問題が巨大な正の整数でも成り立つことを実証しましょう。 コラッツの問題が「9が50個連続する巨大な50桁の整数」でも成り立つこと(最終的に1になること)を確認できるWindows向けコンソールプログラムを作成してください。 ソースコードは、50行以内且つ、DelphiまたはAppmethodに標準搭載されているデータ型、クラス、ライブラリのみを使用して記述してください。 ※コラッツの問題・・ 自然数nに対して、nが奇数なら3をかけて1を加える。 偶数なら2で割る。 この処理を繰り返すとすべての自然数が1になる。 http://ja.wikipedia.org/wiki/コラッツの問題でした。
Delphi でお手軽に巨大な整数を扱うと言えばでおなじみの Data.FmtBcd を使いました。program CollatzMin;usesData.FmtBcd;varBcd: TBcd;Sup: Integer;beginBcd := StrToBcd(StringOfChar('9', 50));while (Bcd > 1) dobeginSup := Bcd.Precision and 1;if((Bcd.Fraction[Bcd.Precision shr 1 + Sup - 1] shr (Sup shl 2) and 1) > 0)thenBcd := Bcd * 3 + 1elseBcd := Bcd / 2;Writeln(BcdToStr(Bcd));end;Readln;end.
結構スッキリしました。program CollatzBcd;usesData.FmtBcd;varN: TBcd;Od: Integer;beginN := StrToBcd(StringOfChar('9', 50));while (N > 1) dobeginOd := BcdPrecision(N) and 1;Od := N.Fraction[BcdPrecision(N) shr 1 + Od - 1] shr (Od shl 2) and 1;N := (N * (1 + Od shl 1) + Od) / 2;Writeln(BcdToStr(N));end;Readln;end.
こちらは49行でギリギリでした!program CollatzBytes;usesSystem.SysUtils;constCOUNT = 50;DIGIT = 9;varBytes: TBytes;i, H, L: Integer;function ToString: String;vari: Integer;beginResult := '';for i := High(Bytes) downto Low(Bytes) doResult := Result + Bytes[i].ToString;Result := Result.TrimLeft(['0']);end;beginSetLength(Bytes, COUNT * 2);for i := 0 to COUNT - 1 doBytes[i] := DIGIT;while (ToString.Length > 1) or (Bytes[0] > 1) dobeginif (Odd(Bytes[0])) thenbeginH := 1;for i := Low(Bytes) to High(Bytes) dobeginL := Bytes[i] * 3 + H;H := L div 10;Bytes[i] := L - H * 10;end;endelse beginL := 0;for i := High(Bytes) downto Low(Bytes) dobeginH := Bytes[i];Bytes[i] := Bytes[i] shr 1 + L;L := (H and 1) * 5;end;end;Writeln(ToString);end;Readln;end.
unit FMX.SystemFontService;interfaceusesFMX.Platform;type// TInterfacedObject と目的のサービスのインターフェースを継承するTFMXSystemFontServiceHook = class(TInterfacedObject, IFMXSystemFontService)private var// 元々 FMX が登録していたサービスを保持する変数FOrgFMXSystemFontService: IFMXSystemFontService;protected// コンストラクタの中でサービスを置き換えるconstructor Create;public// 置き換えたいサービスが実装すべきメソッド{ IFMXSystemFontService }function GetDefaultFontFamilyName: String;function GetDefaultFontSize: Single; inline; // inline ついてはメソッド内にpublic// これを呼ぶとコンストラクタを呼べる!// 今回は Initialization で呼ぶclass procedure RegistService;end;implementationvar// このサービスのインスタンスを保持するSystemFontServiceHook: TFMXSystemFontServiceHook = nil;{ TFMXSystemFontServiceHook }constructor TFMXSystemFontServiceHook.Create;begininherited;// オリジナルの Interface を取り出して自分自身と置き換えてしまう!ifTPlatformServices.Current.SupportsPlatformService( // 取り出しIFMXSystemFontService,IInterface(FOrgFMXSystemFontService))then begin// オリジナルを削除TPlatformServices.Current.RemovePlatformService(IFMXSystemFontService);// 自分を登録しちゃうTPlatformServices.Current.AddPlatformService(IFMXSystemFontService, Self);end;end;function TFMXSystemFontServiceHook.GetDefaultFontFamilyName: String;begin// 元々のサービスが返す値を変えちゃう!Result := 'メイリオ';end;function TFMXSystemFontServiceHook.GetDefaultFontSize: Single;begin// 元々のサービスの値を返すこともできる// 置き換える予定の無いメソッドについては inline 指定をすると// 呼び出しオーバーヘッドが少なくなる// と思ったのですが、そんなことは無いそうです!!// 詳しくは、Lyna さんのこのツイートをご覧くださいResult := FOrgFMXSystemFontService.GetDefaultFontSize;end;// Initialization で↓このメソッドを呼んでコンストラクタを呼び出す// class constractor でも可能// これによって、このユニットをプロジェクトを追加するだけで自動的に置き換わる!class procedure TFMXSystemFontServiceHook.RegistService;beginif (SystemFontServiceHook = nil) thenSystemFontServiceHook := TFMXSystemFontServiceHook.Create;end;initializationTFMXSystemFontServiceHook.RegistService;end.
unit uBraodcastReceiver;interfaceusesSystem.Classes, System.Generics.Collections, FMX.Platform, Androidapi.JNIBridge, Androidapi.JNI.App, Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes, Androidapi.Helpers // XE6 では FMX.Helpers.Android にしてください;type// 直接 class(TJavaLocal, JFMXBroadcastReceiverListener) を定義するとダメ!// グローバル変数にインスタンスをつっこんでも削除されて、Broadcast 受信で// アプリが落ちる!// なので、TInterfacedObject を継承していないクラスから派生したクラスの// インナークラスとして JFMXBroadcastReceiverListener を定義する// このクラスは自動的に削除されないため、上手く動作する!TBroadcastReceiver = classpublic type// Broadcast Receiver を通知するイベント// JString にしているので、Intent.ACTION_XXX と equals で比較可能TBroadcastReceiverEvent = procedure(const iAction: JString) of object;// JFMXBroadcastReceiver を実装した JavaClass として Listener を定義TBroadcastReceiverListener =class(TJavaLocal, JFMXBroadcastReceiverListener)private varFBroadcastReceiver: TBroadcastReceiver;publicconstructor Create(const iBroadcastReceiver: TBroadcastReceiver);// Broadcast Receiver から呼び出されるコールバックprocedure onReceive(context: JContext; intent: JIntent); cdecl;end;private var// つぎの2つは保存しないと消えて無くなる!FBroadcastReceiverListener: JFMXBroadcastReceiverListener;FReceiver: JFMXBroadcastReceiver;// 通知対象の ACTION を保持している変数FActions: TList<String>;// イベントハンドラFOnReceived: TBroadcastReceiverEvent;protectedconstructor Create;// Broadcast Receiver の設定と解除procedure SetReceiver;procedure UnsetReceiver;publicdestructor Destroy; override;// 通知して欲しい ACTION の登録と削除procedure AddAction(const iActions: array of JString);procedure RemoveAction(const iAction: JString);procedure ClearAction;// Boradcast Receiver を受け取った時のイベントproperty OnReceived: TBroadcastReceiverEventread FOnReceived write FOnReceived;end;// Boradcast Receiver のインスタンスを返すfunction BroadcastReceiver: TBroadcastReceiver;implementationusesSystem.UITypes, Androidapi.NativeActivity, FMX.Forms;// Braodcast Receiver の唯一のインスタンスvarGBroadcastReceiver: TBroadcastReceiver = nil;function BroadcastReceiver: TBroadcastReceiver;beginif (GBroadcastReceiver = nil) thenGBroadcastReceiver := TBroadcastReceiver.Create;Result := GBroadcastReceiver;end;{ TBroadcastReceiver.TBroadcastReceiverListener }constructor TBroadcastReceiver.TBroadcastReceiverListener.Create(const iBroadcastReceiver: TBroadcastReceiver);begininherited Create;FBroadcastReceiver := iBroadcastReceiver;end;procedure TBroadcastReceiver.TBroadcastReceiverListener.onReceive(context: JContext;intent: JIntent);varJStr: String;Str: String;procedure CallEvent;varAction: String;begin// Broadcast は Delphi のメインスレッドで届くわけでは無いので// Synchronize で呼び出すAction := JStr;TThread.CreateAnonymousThread(procedurebeginTThread.Synchronize(TThread.CurrentThread,procedurebeginif (Assigned(FBroadcastReceiver.FOnReceived)) thenFBroadcastReceiver.FOnReceived(StringToJString(Action));end);end).Start;end;begin// Broadcast を受け取ったら、このメソッドが呼ばれる!JStr := JStringToString(intent.getAction);for Str in FBroadcastReceiver.FActions doif (Str = JStr) thenCallEvent;end;{ TReceiverListener }procedure TBroadcastReceiver.AddAction(const iActions: array of JString);varStr: String;JStr: String;Action: JString;OK: Boolean;Changed: Boolean;beginChanged := False;for Action in iActions dobeginOK := True;JStr := JStringToString(Action);for Str in FActions doif (Str = JStr) thenbeginOK := False;Break;end;if (OK) then beginFActions.Add(JStr);Changed := True;end;end;if (Changed) thenSetReceiver;end;procedure TBroadcastReceiver.ClearAction;beginFActions.Clear;UnsetReceiver;end;constructor TBroadcastReceiver.Create;begininherited;FActions := TList<String>.Create;// Boardcast Receiver を設定SetReceiver;end;destructor TBroadcastReceiver.Destroy;begin// Broadcast Receiver を解除UnsetReceiver;FActions.DisposeOf;inherited;end;procedure TBroadcastReceiver.RemoveAction(const iAction: JString);vari: Integer;JStr: String;beginJStr := JStringToString(iAction);for i := 0 to FActions.Count - 1 doif (FActions[i] = JStr) thenbeginFActions.Delete(i);SetReceiver;Break;end;end;procedure TBroadcastReceiver.SetReceiver;varFilter: JIntentFilter;Str: String;beginif (FReceiver <> nil) thenUnsetReceiver;// Intent Filter を作成Filter := TJIntentFilter.JavaClass.init;for Str in FActions doFilter.addAction(StringToJString(Str));// TBroadcastReceiverListener を実体とした BroadcastReceiver を作成FBroadcastReceiverListener := TBroadcastReceiverListener.Create(Self);FReceiver :=TJFMXBroadcastReceiver.JavaClass.init(FBroadcastReceiverListener);try// レシーバーとして登録SharedActivityContext.getApplicationContext.registerReceiver(FReceiver,Filter);exceptend;end;procedure TBroadcastReceiver.UnsetReceiver;begin// アプリケーションが終了中でなければ、BroadcastReceiver を解除if(FReceiver <> nil) and(not (SharedActivityContext as JActivity).isFinishing)thentrySharedActivityContext.getApplicationContext.unregisterReceiver(FReceiver);exceptend;FReceiver := nil;end;initializationfinalizationif (GBroadcastReceiver <> nil) thenGBroadcastReceiver.DisposeOf;end.
type// JString は Androidapi.JNI.JavaTypes に// JIntent は Androidapi.JNI.GraphicsContentViewText に// JStringToString は Androidapi.Helpers に// それぞれ定義されていますTForm1 = class(TForm)procedure FormCreate(Sender: TObject);privateprocedure Received(const iAction: JString);publicend;varForm1: TForm1;implementationusesuBraodcastReceiver;{$R *.fmx}procedure TForm1.FormCreate(Sender: TObject);beginBroadcastReceiver.OnReceived := Received;// スクリーン ON / OFF を受け取るように設定BroadcastReceiver.AddAction([TJIntent.JavaClass.ACTION_SCREEN_OFF,TJIntent.JavaClass.ACTION_SCREEN_ON]);end;procedure TForm1.Received(const iAction: JString);beginLog.d('Broadcast Received = ' + JStringToString(iAction));end;
下記の文字列を標準出力せよ >++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.でした。
deathma colosseumという文字列を出力するコードだと解ります。
">"+(文字コード分の"+")+"."を出力すればいいという事になります。
for PChar(@argc)^in'deathma colosseum'do Write(^~,StringOfChar('+',argc),'.')
変数名 | 型 | 本来の意味 |
argc | Integer | 引数の数 |
argv | PPChar | 引数へのポインタ(256 byte 確保済み) |
envp | PPChar | 環境ブロックへのポインタ(256 byte 確保済み) |
function p: Byte;beginp := 1;end
Writeln('deathma colosseum'[1]);
Writeln(('deathma colosseum')[1]);
Writeln((function:String begin Result:='deathma colosseum'end)());
デスマコロシアムでは元々書いてある部分(program ideone; begin end.)は文字数に入りません。var i,j:Byte;for i:=1to 17do begin Write('>');for j:=1to Ord(('deathma colosseum')[i])do Write('+');Write('.');end
こんなメソッド(メッセージ)が定義されています。-webView:shouldStartLoadWithRequest:navigationType:-webViewDidStartLoad:-webViewDidFinishLoad:-webView:didFailLoadWithError:
で、あとは、下記のようにすればイベントが呼ばれます。UIWebViewDelegate = interface(IObjectiveC)['{25E7C20B-68A2-4011-9D7F-B97647BD48C0}']procedure webView(webView: UIWebView; didFailLoadWithError: NSError);cdecl; overload;function webView(webView: UIWebView;shouldStartLoadWithRequest: NSURLRequest;navigationType: UIWebViewNavigationType): Boolean; cdecl; overload;procedure webViewDidFinishLoad(webView: UIWebView); cdecl;procedure webViewDidStartLoad(webView: UIWebView); cdecl;end;TiOSWebViewDelegate = class (TOCLocal, UIWebViewDelegate)publicprocedure webView(webView: UIWebView; didFailLoadWithError: NSError);overload; cdecl;function webView(webView: UIWebView;shouldStartLoadWithRequest: NSURLRequest;navigationType: UIWebViewNavigationType): Boolean; overload; cdecl;procedure webViewDidFinishLoad(webView: UIWebView); cdecl;procedure webViewDidStartLoad(webView: UIWebView); cdecl;end;
というか一般的なデリゲートの作り方と使い方は、むしろ Team J の「FireMonkey iOS - event delegateの使い方のサンプル」の記事の方が詳しいので、そちらをご覧ください。FDelegate := TiOSWebViewDelegate.Create;FWebView.setDelegate(FDelegate.GetObjectID);
こんな風に定義されているものが- (BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType-(void)webView:(UIWebView *)webViewdidFailLoadWithError:(NSError *)error
こうなるわけですが、ここで見てほしいのが "overload" です。procedure webView(webView: UIWebView;didFailLoadWithError: NSError); cdecl; overload;function webView(webView: UIWebView;shouldStartLoadWithRequest: NSURLRequest;navigationType: UIWebViewNavigationType): Boolean; cdecl; overload;
こんな感じで、引き数名は全部違うものの型は全部 WebViewFrame です!!-webView:didStartProvisionalLoadForFrame:-webView:didFinishLoadForFrame:-webView:didCommitLoadForFrame:-webView:willCloseFrame:-webView:didChangeLocationWithinPageForFrame:
こうなります。しかし、引数の型が全部同じなので、コンパイラに怒られます!WebFrameLoadDelegate = interface(IObjectiveC)procedure webView(sender: WebView;didStartProvisionalLoadForFrame: WebFrame); overload; cdecl;procedure webView(sender: WebView;didFinishLoadForFrame: WebFrame); overload; cdecl;procedure webView(sender: WebView;didCommitLoadForFrame: WebFrame); overload; cdecl;procedure webView(sender: WebView;willCloseFrame: WebFrame); overload; cdecl;procedure webView(sender: WebView;didChangeLocationWithinPageForFrame: WebFrame); overload; cdecl;end
まさかのコメントアウト!!! oh...UIPickerViewDelegate = interface(IObjectiveC)// procedure pickerView(// pickerView: UIPickerView;// didSelectRow: NSInteger;// inComponent: NSInteger); cdecl; overload;// function pickerView(// pickerView: UIPickerView;// rowHeightForComponent: NSInteger): Single; cdecl; overload;function pickerView(pickerView: UIPickerView;titleForRow: NSInteger;forComponent: NSInteger): NSString; cdecl; overload;// function pickerView(// pickerView: UIPickerView;// viewForRow: NSInteger;// forComponent: NSInteger;// reusingView: UIView): UIView; cdecl; overload;end;
こんな感じで定義できます!typeWebFrame2 = type WebFrame;WebFrame3 = type WebFrame;WebFrame4 = type WebFrame;WebFrame5 = type WebFrame;WebFrameLoadDelegate = interface(IObjectiveC)procedure webView(sender: WebView;didStartProvisionalLoadForFrame: WebFrame); overload; cdecl;procedure webView(sender: WebView;didFinishLoadForFrame: WebFrame2); overload; cdecl;procedure webView(sender: WebView;didCommitLoadForFrame: WebFrame3); overload; cdecl;procedure webView(sender: WebView;willCloseFrame: WebFrame4); overload; cdecl;procedure webView(sender: WebView;didChangeLocationWithinPageForFrame: WebFrame5); overload; cdecl;end
というプロパティが定義されています。@property(readonly) NSEventType type
こうなっています。NSEvent = interface(NSObject)function &type: NSEventType; cdecl;end;