2013年8月23日 星期五

Uva 100 - The 3n+1

問題網址
有幾點要考慮:
  1. 讀取的行數不是單行
  2. 每行的兩個數值,不一定是前小後大
#include <stdio.h>
int cycleLength(int number);
int main()
{
  int i, j, input1, input2;
 
  while( scanf("%d %d",&input1, &input2) != EOF ){
  
      //檢查與調整前後大小
      if(input1 < input2){
          i = input1;
          j = input2;
      }else{
          i = input2;
          j = input1;
      }
  
  
      int maxCycleLength = 0;
      long int x;
      
      for ( x = i; x <=j ; x++){
          int c = cycleLength(x) ;
          if (c > maxCycleLength){
              maxCycleLength = c ;
          }
      }
      printf("%d %d %d\n",input1,input2, maxCycleLength );
 }
 
 
 return 0;
}

int cycleLength(int number)
{
    int c = 1;
    while(number!=1){
        if(number%2==1){
            number = 3*number +1;
            c++;
        }else{
            number = number/2;
            c++;
        }
    }
 return c;
}


解了此題,但是速度太慢(run time:0.612),要嘗試用別種方法

2013年8月16日 星期五

Objective-C Protocols

要求類別一定要實現某些方法時,需要用的到 protocol,代理人模式中 (delegate)常常見到,因為類別在成為另一個類別的代理時,必須實作一些方法以達成代理人的角色。而Objective-C中,因為沒有多重繼承,利用 protocol可以使一個類別具有多重型別的方法。

舉個例子,我們可以定義一些 protocols,@protocol 和 @end 之中宣告要實現的方法,方法的預設值都是required,使用關鍵字@optional將它之下的變成不是必須的,如果是使用新增檔案的方式加入protocol,預設這些 protocols也遵守 (<>) NSObject這個 protocol 。

Behavior.h

@protocol <NSObject>
@optional
-(void)fly;
@required
-(void)run;
-(void)sleep;
@end

Think.h

@protocol <NSObject>
-(void)getRabbit;
-(void)escape;
@optional
-(void)calculate;
@end

然後建立一個類別 Dog , conform/adopt  these protocols,有多個 protocols,用逗點隔開

Dog.h

@interface Dog : NSObject <Behavior, Think>

@end

Dog.m

@implemention Dog
-(void)run
{
    ........
}
-(void)sleep
{
    ........
}
-(void)getRabbit
{
    ........
}
-(void)escape
{
    ........
}
@end

想確認某個物件是否confirm protocol,可以這樣作

id someObject;
......
if ([someObject confirmsToProtocol : @protocol(Think) ] == YES){
    // do something
}

用來宣告型別遵守某些 protocol

id <protocol3, protocol2> someObject ;

2013年8月15日 星期四

Objective-C -- 多型 Polymorphism

polymorphism is a programming language feature that allows values of different data types to be handled using a uniform interface. The concept of parametric polymorphism applies to both data types and functions.
.. from wiki

透過相同的界面進行不同的操作,多型可以應用在資料型別與方法上

書中的解釋更為簡單,Same name, Different Class,不同的類別,相同的名稱,舉個例子,就像是同樣都是叫,鴨子類別中的叫可能是呱呱呱,狗的類別的叫則是汪汪汪。

Animal.h
#import <Foundation/Foundation.h>

@interface Animal : NSObject
{
    NSString *_name;
}
-(void)bray;
@end
Animal.m
#import "Animal.h"

@implementation Animal

-(void)bray
{
    NSLog(@"A......");
}

@end

Duck.h
#import "Animal.h"

@interface Duck : Animal

@end
Duck.m
#import "Duck.h"

@implementation Duck

-(void)bray
{
    NSLog(@"Caw..Caw..Caw.....");
}

@end
Dog.h
#import "Animal.h"

@interface Dog : Animal

@end
Dog.m
#import "Dog.h"

@implementation Dog

-(void)bray
{
    NSLog(@"Wow...Wow..www");
}

@end
main.m
#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Duck.h"
#import "Dog.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        id foo;
        //First subclass
        foo = [[Duck alloc]init];
        [foo bray];
        //Second subclass
        foo = [[Dog alloc]init];
        [foo bray];
        
    }
    return 0;
}

輸出結果:




main.m 當中的 id 是objective-C中泛指所有類別的型別,在其他的語言中,如果沒有這種型別,id 改為 Animal一樣可以,而在Objective-C中兩者都可以使用。
foo變數先指到Duck之後指向Dog,雖然方法名稱都是一樣,但是會根據個別類別中的方法去表現。多型的優點就是,不需要取很多的方法名稱,鴨子叫,狗叫,貓叫...,只要執行時去判斷是哪個類別,在找出相對應的方法即可。

Dynamic typing, dynamic binding

前者是指在執行的過程中,物件動態決定屬於哪個類別,後者則是根據哪種類別去執行方法,用上述的例子來說明

foo = [[Dock] alloc] init];   // dynamic typing
[foo bray];                         // dynamic binding

In runtime決定型別固然很強大,但也有缺點,首先在編譯時,complier無法檢查是否有相對應的方法存在,相反地,如果是用靜態型別 static typing,complier 會確保每個方法對應到正確物件,這可以讓我們在編譯時就發現錯誤而不是在執行的時候,因為你永遠不知道使用者會如何操作,意謂者你不可能測試完所有的可能 ; 再者,使用大量的  id,會讓程式的可讀性降低。

2013年8月14日 星期三

Objective-C Inheritance

繼承總要有個來源,在Objective-C 中, NSObject 是所有的類別的源頭,所以時常可以看到
@interface ClassA : NSObject
    ................
@end

self, super
-(id)init
{
    self = [super init];
    if(self) {
        // Initialize code here
    }
    return self;
}

在建構子中,我們常常這樣寫,self 表示自己,super則是父類別,而這段程式是先使用父類別的建構子,如果生成成功,進行子類別的初始化工作,最後回傳。

@class

在類別中要使用別的類別,通常我們都在.h檔中去import另一個類別的標頭檔,
#import "ClassB.h"  // ClassA.h
也可以使用@class這個關鍵字去告訴complier,會更有效率的多
@class ClassB     // ClassA.h
這裡會用到ClassB這個類別,你不用知道它的內容是什麼,儘管編譯過就是了。但事情沒這麼簡單,如果在ClassA.m檔中,有用到ClassB的方法,這時候編譯器怎麼會知道ClassB中的方法內容,就會出現錯誤。



把ClassA.m 檔中匯入ClassB.h檔就可以解決這個問題

#import "ClassB.h"   // ClassA.m

那為何不一開始就在ClassA.h中,直接import ClassB.h檔就好了呢,是啊!!這樣不是多此一舉嗎~~所以使用時機是當你不會用到另一個類別的方法時,用 @class節省編譯很多時間。

另外,有一種情況是非用不可,那就是 circular inclusions,
#import "ClassB.h"  // ClassA.h
#import "ClassA.h" //  ClassB.h

這裡就需要用到@class,就不會再編譯的階段一直無窮的交互import。下面的例子,因為都有用到對方的方法,所以在.m中都需要 import 對方的.h檔。

ClassA.h
#import <Foundation/Foundation.h>
@class  ClassB;
@interface ClassA : NSObject
{
    NSString *name;
    ClassB *b;
}

-(NSString *)name;
-(NSString *)theNameOfB;

@end
ClassA.m
#import "ClassA.h"
#import "ClassB.h"

@implementation ClassA
-(id)init
{
    self = [super init];
    if (self) {
        name = @"A";
    }
    return self;
}

-(NSString *)name
{
    return name;
}
-(NSString *)theNameOfB
{
    if (!b) {
        b = [[ClassB alloc]init];
    }
    return b.name;
}
@end

ClassB.h
#import <Foundation/Foundation.h>
@class ClassA;

@interface ClassB : NSObject
{
    ClassA *a;
    NSString *name;
}

-(NSString *)name;
-(NSString *)theNameOfA;

@end
ClassB.m
#import "ClassB.h"
#import "ClassA.h"

@implementation ClassB


-(id)init
{
    
    self = [super init];
    if (self) {
        name = @"B";
    }
    return self;
    
}

-(NSString *)name
{
    return name;
}

-(NSString *)theNameOfA
{
    if (!a) {
        a = [[ClassA alloc]init];
    }
    return a.name;
}

@end

main.m
#import <Foundation/Foundation.h>
#import "ClassA.h"
#import "ClassB.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        ClassA *a = [[ClassA alloc]init];
        NSLog(@"ClassA use classB method, the name of ClassB : %@",[a theNameOfB]);
        
        ClassB *b = [[ClassB alloc]init];
        NSLog(@"ClassB use classA method, the name of ClassA : %@",[b theNameOfA]);
    }
    return 0;
}


輸出結果

2013年8月13日 星期二

Objective-C Enumerated Data Types

enum 

列舉的優點就是將整數與符號名稱作連接,讓程式的可讀性變好,容易維護,而不需要去記某個數字代表的意義。
enum color{ red = 1, orange, yellow, green, blue, indigo, purple};

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        
        enum color displayColor = blue;
        NSString *displayColorStr;
        
        switch (displayColor) {
            case red:
                displayColorStr = @"紅";
                break;
            case orange:
                displayColorStr = @"橙";
                break;
            case yellow:
                displayColorStr = @"黃";
                break;
            case green:
                displayColorStr = @"綠";
                break;
            case blue:
                displayColorStr = @"藍";
                break;
            case indigo:
                displayColorStr = @"靛";
                break;
            case purple:
                displayColorStr = @"紫";
                break;
                
            default:
                displayColorStr = @"數值有誤";
                break;
        }
        
        NSLog(@"目前的顯示器顏色為:%@",displayColorStr);
    }
    return 0;
}

Anonymous enum 匿名列舉

enum {red = 1, orange, yellow, green, blue, indigo, purple} displayColor ;

沒有名稱,變數緊接著宣告,使用時機,當你懶得取名稱時 :) (大誤)
而宣告時一直打enum也挺煩的,這時可以用 typedef 關鍵字。

typedef

typedef enum {red = 1, orange, yellow, green, blue, indigo, purple} Color ;

Color display = red;

2013年8月9日 星期五

Objective-C Variables

Local Variables 

區域變數只存活於它所在的區塊內,能存取它的範圍也在那個區域,而程式執行完那段後,變數即消失。

-(void)saveMoney
{
     int capital = 0;
     capital++;
     NSLog(@"Capital : %d",capital);
}
每當saveMoney這個方法被呼叫時,變數在此初始化並賦值,然後加一,而在這個區域中,可以存取到capital變數,但是不管執行saveMoney這個方法幾次,Capital永遠都是1,因為方法執行完後,變數capital就消失了。如果要保留此變數所存的值,勢必要使用別種方法。

static

-(void)saveMoney
{
     static int capital = 0;
     capital++;
     NSLog(@"Capital : %d",capital);
}
如果我在變數前面加上關鍵字 static,那麼這個變數只會被初始化並賦值一次,並不會每次呼叫此方法時都重複作一次,故第一次執行saveMoney時,initialize capital and add 1 ,第二次加一,第三次再加一,一直下去。

不過這樣的寫法,capital只能在saveMoney中被存取,把它移到implement外,這樣在implement中的其他方法也都可以存取它囉,邏輯上也更清楚。

#import "Cheapskate.h"
static int capital;
@implemention Cheapskate
-(void)saveMoney
{
     static int capital = 0;
     capital++;
}

-(void)showMoney
{
     NSLog(@"Capital : %d",capital);
}
@end

Instance  Variable Scope

@protected      self and subclass (default)
@private        self
@public         any other class
如果是public instance variable,可以使用 pointer operator ( ->)

Global Variable

在程式的開始,任何方法、類別宣告(@interface)、struct declaration之外,可以宣告與定義全域變數,變數的名稱前面慣例加上g,表示全域。全域變數的使用要很小心,除錯時很難找,儘量少用,如果真的要用,名稱要取的好一些,建議前面加上g。

int gVariable = 0 ;


如果只有declaration沒有definition的話,基礎型別用預設值,int 0,objective-C object則是nil,如果是複雜的definition,無法在宣告的同時也定義,可以在其他地方作定義,例如,main()、application delegate init method, applicationDidFinishLaunching method ..

NSArray *array = [[NSArray alloc] initWithObjects:@"one",@"two",nil]; 
// Initializer element is not a compile-time constant
如果在 global variable 前面加上 static ,那這個變數的可見域就只限於此 implementation file,不再是全域變數了,變成了像是 class variable

External Variables

外部變數,顧名思義就是宣告在外的變數,:(,通常和全域變數一起用,告訴complier這個變數已經在外部宣告並定義過了,我在這個檔案或區域中要使用。記得,在使用extern 時,不可以再定義。

extern int gVariable = 10; // error

const 

無法再修改值的變數,這意味著在開始的時候就必須給定值,良好的編程習慣是,當你知道某個變數的值不應該再變動時,就加上const,別人也一目了然。

const double pi = 3.14159;

volatile

揮發易變的變數,使用的原因是為了預防編譯器把變數最佳化,以下是wiki的例子:

static int foo;
void bar(void) {
    foo = 0;
 
    while (foo != 255)
         ;
}
similar to this
void bar_optimized(void) {
    foo = 0;
 
    while (true)
         ;
}
foo變數有可能在外部會進行修改(例如:delegate),加上volatile 避免編譯器的最佳化。
static volatile int foo;
 
void bar (void) {
    foo = 0;
 
    while (foo != 255)
        ;
}

First Father's Day

Dear 小米,

昨天是阿爸我的第一個父親節,雖然你還不會開口說話,不過在我抱著你時,你嘴角微微上揚的表情已經讓我十分開心,一掃整日的陰霾。

阿爸的手機今天當掉了,壞得很徹底,我並不心疼系統壞掉,而是難過失去了你的一些珍貴照片,從你出生後,大部分都是用手機幫你拍照,生產房、醫院、月子中心,全部不見了我會很內疚的,還好系統有自動備份照片30天的功能,所以最後只有幾張在產房的照片找不回來。經過這次的教訓,阿爸我會常常備份照片,也會挑選幾張不錯得上傳至部落格,也打算買一台好一點的相機幫你記錄。

剛出生,護士阿姨幫你洗好澡戴上帽子的模樣

每個新生兒都是一直睡,你也不例外,
3440克的體重,看起來非常可愛。

睡覺的時候不喜歡被包的緊緊的你,最愛伸出手,
夢想著拯救世界。

阿屋

衝啊

休息一下

終於有一張是睡醒的模樣

就是跪著也要繼續睡

天使
擦上眼藥膏,泛著淚光

月子中心的嬰兒房總是亮著燈,
阿爸我知道你還想睡。

護士阿姨把你照顧的很好,白白淨淨的


2013年8月8日 星期四

Objective-C DataTypes

Basic data types:

  • int                20          %i
  • float             20.5f      %f
  • double         2.2e-10  %e  /  %g  ( %g讓系統判斷是否使用科學記號,<-4>5 )
  • char            'W'          %c
double 的精準度大概是 float 的兩倍,Complier會自動將有小數點的數值視為double,如果要強制為float,在數值後面加上f (7.65f)。把char連起來就是character string,而以這些型別的數值或字串都是constant,如 8, 8.6, 'x', @"Objective-c"。

                     前綴字     例          十進位數值            NSLog format characters
八進位     /   0           /   040     /     8*4 = 32                        %o
十六進位 /   0x         /   0x2F   /     2*16 + 15 = 47              %#x


Qualifiers:

  • long             根據系統擴充儲存的bit,
                              在大多數系統裡,long int 、int 都是32bits。  21000800L      %li
  • long long      保證至少64bits  %lli
  • short            少一點bits,不過不會少於16bits   %hi
  • unsigned      都是正數   10000U
  • signed          預設值


Type id
id為任意型別,在多型與動態綁定中用的很多。

備註:表示Example表示NSLog chars。

2013年8月7日 星期三

Python 學習筆記


  • 中文出現錯誤,在程式碼開頭加上:

          # encoding: utf-8


  • Before      Python 3.0      After    

          raw_input  取得字串    -->   改名為 input
          input          取值            -->   取消,可以改用 eval(input())