開発者Yandex.Music for iOSのタスク

開発者の地位に関するアンケートに記入する際、Yandex.Musics for iOSはテストタスクを完了するよう求められます。 タスクは開かれた形式で配置され、タスクを明かしたり、決定を公開したりする要求はありません。



始めましょう。



質問1.認可システムでは、ログイン形式に次の制限があります。ラテン文字で始まり、ラテン文字、数字、ピリオド、マイナスで構成され、ラテン文字または数字で終わる必要があります。 最小ログイン長は1文字です。 最大-20文字。



入力文字列がこのルールに一致するかどうかを確認するコードを記述します。



正規表現を使用します。 NSRegularExpressionクラスはiOS 4.0で登場しました。

BOOL loginTester(NSString* login) { NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\A[a-zA-Z](([a-zA-Z0-9\\.\\-]{0,18}[a-zA-Z0-9])|[a-zA-Z0-9]){0,1}\\z" options:NSRegularExpressionCaseInsensitive error:&error]; //     ,       //     -  . NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:login options:0 range:NSMakeRange(0, [login length])]; return (BOOL)(rangeOfFirstMatch.location!=NSNotFound); }
      
      





このコードを使用し完成したプロジェクトを次に示します。 テストできます。

この質問は、正規表現を恐れる人を排除することを目的としているように思えます。



質問2.入力文字列で最も頻繁に出現するN個の単語を返すメソッドを記述します。



もっと面白い。



 -(NSArray*)mostFrequentWordsInString:(NSString*)string count:(NSUInteger)count { //   . //        . //  ,  ,      , //   enumerateSubstringsInRange   NSStringEnumerationByWords NSMutableCharacterSet *separators = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy]; [separators formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; NSArray *words = [string componentsSeparatedByCharactersInSet:separators]; NSCountedSet *set = [NSCountedSet setWithArray:words]; //    enumerateByCount,   . //    NSMutableArray *selectedWords = [NSMutableArray arrayWithCapacity:count]; NSMutableArray *countsOfSelectedWords = [NSMutableArray arrayWithCapacity:count]; for (NSString *word in set) { NSUInteger wordCount = [set countForObject:word]; NSNumber *countOfFirstSelectedWord = [countsOfSelectedWords count] ? [countsOfSelectedWords objectAtIndex:0] : nil; //  iOS 7  firstObject if ([selectedWords count] < count || wordCount >= [countOfFirstSelectedWord unsignedLongValue]) { NSNumber *wordCountNSNumber = [NSNumber numberWithUnsignedLong:wordCount]; NSRange range = NSMakeRange(0, [countsOfSelectedWords count]); NSUInteger indexToInsert = [countsOfSelectedWords indexOfObject:wordCountNSNumber inSortedRange:range options:NSBinarySearchingInsertionIndex usingComparator:^(NSNumber *n1, NSNumber *n2) { NSUInteger _n1 = [n1 unsignedLongValue]; NSUInteger _n2 = [n2 unsignedLongValue]; if (_n1 == _n2) return NSOrderedSame; else if (_n1 < _n2) return NSOrderedAscending; else return NSOrderedDescending; }]; [selectedWords insertObject:word atIndex:indexToInsert]; [countsOfSelectedWords insertObject:wordCountNSNumber atIndex:indexToInsert]; //       ,       if ([selectedWords count] > count) { [selectedWords removeObjectAtIndex:0]; [countsOfSelectedWords removeObjectAtIndex:0]; } } } return [selectedWords copy]; //      selectedWords, //    immutable   mutable   -     } //     :            .
      
      





実際のiOSアプリケーションでこの問題を解決する必要がある場合、検索用の入力データがどこから来るのかを理解し、入力文字列のサイズが数メガバイトを超えないと仮定すると、まさにこのアプローチを使用します。 私の意見では、iOSアプリケーションのかなり合理的な仮定です。 それ以外の場合、入力には行がなく、ファイルがあります。 入力データが非常に大きい場合、1つの中間配列を削除するには、単語を反復処理するための正規表現に注意する必要があります。 そのような正規表現は言語に非常に依存しています-ロシア語で機能するものは中国語でも失敗しません。 しかし、次の言葉で何をすべきか-簡単なアルゴリズムを除いて、何も思い浮かびません。 最も頻繁に出現する単語を1つ選択する必要がある場合-これが高速多数決です。 しかし、このアルゴリズムの全体的な美しさは、単一の値を選択するように機能することです。 N値を選択するためのアルゴリズムの変更は、私にはわかりません。 自分で修正できませんでした。



質問3. NSURLConnectionを使用して、HTTPを介してテキストドキュメントを非同期にロードするメソッドを記述します。 その使用例を示してください。



 -(void)pullTextFromURLString:(NSString*)urlString completion:(void(^)(NSString*text))callBack { NSURLRequest *request = [NSURLRequest requestWithURL: [NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { if (error) { NSLog(@"Error %@", error.localizedDescription); } else { // ,     ,     callBack( [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding] ); } }]; }
      
      







ここではすべてが簡単です。 おそらく、最初の質問のように、この質問はわからない/わからない。



質問4.以下のコードに表示されるすべての問題をリストします。 それらを修正する方法を提案します。

 NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < 1000; ++i) { if ([operation isCancelled]) return; process(data[i]); } }]; [queue addOperation:operation];
      
      







個人的には、ブロックの作成時にブロックによって「キャプチャ」される操作変数がまだ最後まで初期化されていないという問題があります。 「キャプチャ」時にこの変数の値が実際にどのようになるかは、このコードがクラスメソッドで使用されるか、単純な関数で使用されるかによって異なります。 生成されたコードが完全に機能する可能性はありますが、このコードは私には明らかではありません。 状況から抜け出すには? だから:



 NSBlockOperation *operation = [[NSBlockOperation alloc] init]; [operation addExecutionBlock:^{ for (int i = 0; i < 1000; ++i) { if ([operation isCancelled]) return; process(data[i]); } }]; [queue addOperation:operation];
      
      





おそらく、__ block修飾子を操作変数の宣言に追加するだけで十分でしょう。 しかし、上記のコードのように-確かに。 操作変数の__weakコピーを作成して、ブロック内で使用するものもあります。 よく考えた後、この特定のケースでは、変数操作とブロックの有効期間がわかっている場合、これは不要であると判断しました。 まあ、そのような複雑な設計にはNSBlockOperationを使用する価値があると思っていたでしょう。 私は合理的な議論をすることはできません-個人的な好みの問題。



このコードには他に何が間違っていますか? コード内のさまざまな魔法の定数は好きではありませんが、1000の代わりにdefine、const、sizeofなどを使用します。



Objective-Cの長いサイクルでは、自動解放された変数について覚えておく必要があり、そのような変数が関数またはプロセスメソッドで使用され、このメソッドまたは関数がそれを気にしない場合、この呼び出しを@autoreleasepool {}でラップする必要があります。 ループの各反復で新しいプールを作成すると、オーバーヘッドまたは冗長になる場合があります。 ARCを使用しない場合、ループの10回の繰り返しごとに新しいNSAutoreleasePoolを作成できます。 ARCが使用されている場合、これは不可能です。 ところで、これがおそらくARCを使用しない唯一の理由です。



コードによると、処理中にデータが変更されるかどうか、他のスレッドから他の誰かが処理中にこのデータにアクセスするかどうか、使用されるデータ構造、プロセス自体が必要なときにデータへの排他的アクセスを処理するかどうかは明確ではありません。 あなたはロックの世話をする必要があるかもしれません。



質問5.表があります。



 CREATE TABLE tracks ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, PRIMARY KEY (id) )
      
      





 CREATE TABLE track_downloads ( download_id BIGINT(20) NOT NULL AUTO_INCREMENT, track_id INT NOT NULL, download_time TIMESTAMP NOT NULL DEFAULT 0, ip INT NOT NULL, PRIMARY KEY (download_id) )
      
      





1000回以上ダウンロードされたトラックの名前を返すクエリを作成します。



これは素晴らしい仕事をするリクエストです:

 select name from tracks where id in (select track_id from (select track_id, count(*) as track_download_count from track_downloads group by track_id order by track_download_count desc) where track_download_count > 1000)
      
      





sqliteでチェックイン。 私は1つの選択で減らすことができると思いますが、どうすればいいのか分かりません。

割り当て内のこの質問の存在は非常に理解しやすいです-これはアプリケーションが行うことです。



批判を待っています。



All Articles