UINavigationController震动推送过渡(UINavigationController jarring push transition)
我正在使用最新的iOS 7动画转换协议,以便创建一个视频控制器的淡入淡出过渡;
PSSpaceDetailViewController
类的PSSpaceDetailViewController
。 但是,对于所有其他推送转换,我想使用UINavigationController
通常提供的默认推送动画。但是,实现了以下代码才能做到这一点,当我从上述类中推出一个单独的视图控制器时,我收到了一个奇怪的延迟震动动画。 任何想法为什么会这样? 我上传了一段简短的视频,展示了我想要描述的动画,希望能让我更容易理解这个错误: http : //d.pr/v/Q754
//PSAnimatngNavigationControllerDelegate.m + (instancetype) sharedInstance { static PSAnimatingNavigationControllerDelegate *shared; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shared = [[PSAnimatingNavigationControllerDelegate alloc] init]; }); return shared; } - (PSFadeAnimator *) animator { if (!_animator) { _animator = [[PSFadeAnimator alloc] init]; } return _animator; } - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { if (operation == UINavigationControllerOperationPush && [toVC isKindOfClass:[PSSpaceDetailViewController class]]) { return self.animator; } return nil; } // App Delegate.m UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:notesViewController]; [navigationController setDelegate:[PSAnimatingNavigationControllerDelegate sharedInstance]]; PSSpaceDetailViewController.m - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { PSMatchDetailViewController *matchDetail = [[PSMatchDetailViewController alloc] initWithOriginalSpace:self.space andPotentialLead:self.datasource[indexPath.section][indexPath.row]]; [self.navigationController pushViewController:matchDetail animated:YES]; }
I'm using the latest iOS 7 animation transitions protocols in order to create a fade transition one a push a view controller; a member of the class
PSSpaceDetailViewController
. However, for all other push transitions, I'd like to use the default push animation thatUINavigationController
normally provides.However, having implemented the following code to do exactly that, I'm receiving a strange delayed jarring animation when I push a separate view controller from the aforementioned class. Any ideas why this is happening? I've uploaded a short video showing the animation that I'm trying to describe which will hopefully make it easier to understand the bug: http://d.pr/v/Q754
//PSAnimatngNavigationControllerDelegate.m + (instancetype) sharedInstance { static PSAnimatingNavigationControllerDelegate *shared; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shared = [[PSAnimatingNavigationControllerDelegate alloc] init]; }); return shared; } - (PSFadeAnimator *) animator { if (!_animator) { _animator = [[PSFadeAnimator alloc] init]; } return _animator; } - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { if (operation == UINavigationControllerOperationPush && [toVC isKindOfClass:[PSSpaceDetailViewController class]]) { return self.animator; } return nil; } // App Delegate.m UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:notesViewController]; [navigationController setDelegate:[PSAnimatingNavigationControllerDelegate sharedInstance]]; PSSpaceDetailViewController.m - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { PSMatchDetailViewController *matchDetail = [[PSMatchDetailViewController alloc] initWithOriginalSpace:self.space andPotentialLead:self.datasource[indexPath.section][indexPath.row]]; [self.navigationController pushViewController:matchDetail animated:YES]; }
原文:https://stackoverflow.com/questions/21245028
最满意答案
和user5402一样,我很好奇是否等效(对于某些等价的值)C程序会在时限内完成还是超时。 如果愿意的话,看看使用
ByteString
的等效程序是否可以及时完成将会很有趣。 - 并不是ByteString
本身比Text
更快,但由于输入必须转换为Text
的内部表示,而ByteString
按原样转换,这可能会有所不同。ByteString
可能更快的另一个可能原因 - 如果测试机器具有32位GHC - 那么文本的融合至少需要比32位架构上通常可用的寄存器更多才能获得全部利润[很久以前在text-0.5 to text-0.7的日子里,在我的32位盒子里, bytestring过去相当快,不知道是否仍适用于较新的文本版本]。好的,既然user5402已经验证了天真的算法在C语言中足够快,那么我就继续使用
ByteString
编写了一个天真算法的实现。{-# LANGUAGE BangPatterns #-} module Main (main) where import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Unsafe as U import Control.Monad import Data.Word main :: IO () main = do cl <- C.getLine case C.readInt cl of Just (cases,_) -> replicateM_ cases (C.getLine >>= print . similarity) Nothing -> return () -- Just to keep the condition readable. (?) :: B.ByteString -> Int -> Word8 (?) = U.unsafeIndex similarity :: B.ByteString -> Int similarity bs | len == 0 = 0 | otherwise = go len 1 where !len = B.length bs go !acc i | i < len = go (acc + prf 0 i) (i+1) | otherwise = acc prf !k j | j < len && bs ? k == bs ? j = prf (k+1) (j+1) | otherwise = k
并在一些不良案例中将其与OP的
Text
版本进行了比较。 在我的盒子上,这比Text
版本快四倍以上,所以有趣的是它是否足够快(C版本是另一个快4.5倍,所以它可能不是)。但是,我认为由于使用具有二次最坏情况行为的天真算法,更有可能超出时间限制。 可能有一些测试用例会引起天真算法的最坏情况。
因此,解决方案是使用可以更好地,最佳地线性扩展的算法。 计算字符串相似性的一种线性算法是Z算法 。
这个想法很简单(但是,像大多数好主意一样,不容易)。 让我们调用一个(非空)子字符串,它也是字符串前缀子字符串的前缀。 为避免重新计算,该算法使用prefix-substring的窗口,该窗口在当前被认为是最右边扩展的索引之前开始(最初,窗口为空)。
使用的变量和算法的不变量:
i
,正在考虑的索引从1开始(对于基于0的索引;不考虑整个字符串)并且递增到length - 1
left
和right
,prefix-substring窗口的第一个和最后一个索引; 不变量:
left < i
,left <= right < length(S)
,left > 0
或right < 1
,- 如果
left > 0
,那么S[left .. right]
是S
和S[left .. ]
的最大公共前缀,- 如果
1 <= j < i
并且S[j .. k]
是S
的前缀,则k <= right
- 数组
Z
,不变量:对于1 <= k < i
,Z[k]
包含S[k .. ]
和S
的最长公共前缀的长度。算法:
- 设置
i = 1
,left = right = 0
(允许left <= right < 1
任何值),并且对于所有索引1 <= j < length(S)
设置Z[j] = 0
。- 如果
i == length(S)
,请停止。- 如果
i > right
,找到S
和S[i .. ]
的最长公共前缀的长度l
,将其存储在Z[i]
。 如果l > 0
我们发现一个窗口比前一个延伸得更远,那么设置left = i
和right = i+l-1
,否则保持不变。 递增i
并转到2。这里
left < i <= right
,所以子串S[i .. right]
是已知的 - 因为S[left .. right]
是S
的前缀,它等于S[i-left .. right-left]
。现在考虑
S
的最长公共前缀,其中子串从索引i - left
开始i - left
。 它的长度是Z[i-left]
,因此S[k] = S[i-left + k]
0 <= k < Z[i-left]
和
S[Z[i-left]] ≠ S[i-left+Z[i-left]]
。 现在,如果Z[i-left] <= right-i
,则i + Z[i-left]
在已知窗口内,因此S[i + Z[i-left]] = S[i-left + Z[i-left]] ≠ S[Z[i-left]] S[i + k] = S[i-left + k] = S[k] for 0 <= k < Z[i-left]
并且我们看到
S
和S[i .. ]
的最长公共前缀的长度具有长度Z[i-left]
。 然后设置Z[i] = Z[i-left]
,递增i
,然后转到2。否则,
S[i .. right]
是S
的前缀,我们检查它的扩展距离,开始比较right+1
和right+1 - i
的索引。 让长度为l
。 设置Z[i] = l
,left = i
,right = i + l - 1
,增加i
,然后转到2。由于窗口从不向左移动,并且比较总是在窗口结束后开始,因此字符串中的每个字符最多成功一次与字符串中的较早字符进行比较,并且对于每个起始索引,最多只有一个不成功。比较,因此算法是线性的。
代码(使用
ByteString
出于习惯,应该简单地移植到Text
):{-# LANGUAGE BangPatterns #-} module Main (main) where import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Unsafe as U import Data.Array.ST import Data.Array.Base import Control.Monad.ST import Control.Monad import Data.Word main :: IO () main = do cl <- C.getLine case C.readInt cl of Just (cases,_) -> replicateM_ cases (C.getLine >>= print . similarity) Nothing -> return () -- Just to keep the condition readable. (?) :: B.ByteString -> Int -> Word8 (?) = U.unsafeIndex -- Calculate the similarity of a string using the Z-algorithm similarity :: B.ByteString -> Int similarity bs | len == 0 = 0 | otherwise = runST getSim where !len = B.length bs getSim = do za <- newArray (0,len-1) 0 :: ST s (STUArray s Int Int) -- The common prefix of the string with itself is entire string. unsafeWrite za 0 len let -- Find the length of the common prefix. go !k j | j < len && (bs ? j == bs ? k) = go (k+1) (j+1) | otherwise = return k -- The window with indices in [left .. right] is the prefix-substring -- starting before i that extends farthest. loop !left !right i | i >= len = count 0 0 -- when done, sum | i > right = do -- We're outside the window, simply -- find the length of the common prefix -- and store it in the Z-array. w <- go 0 i unsafeWrite za i w if w > 0 -- We got a non-empty common prefix and a new window. then loop i (i+w-1) (i+1) -- No new window, same procedure at next index. else loop left right (i+1) | otherwise = do -- We're inside the window, so the substring starting at -- (i - left) has a common prefix with the substring -- starting at i of length at least (right - i + 1) -- (since the [left .. right] window is a prefix of bs). -- But we already know how long the common prefix -- starting at (i - left) is. z <- unsafeRead za (i-left) let !s = right-i+1 -- length of known prefix starting at i if z < s -- If the common prefix of the substring starting at -- (i - left) is shorter than the rest of the window, -- the common prefix of the substring starting at i -- is the same. Store it and move on with the same window. then do unsafeWrite za i z loop left right (i+1) else do -- Otherwise, find out how far the common prefix -- extends, starting at (right + 1) == s + i. w <- go s (s+i) unsafeWrite za i w loop i (i+w-1) (i+1) count !acc i | i == len = return acc | otherwise = do n <- unsafeRead za i count (acc+n) (i+1) loop 0 0 1
Like user5402, I'd be curious whether an equivalent (for certain values of equivalent) C programme would finish within the time limit or also time out. If it would, it would be interesting to see whether an equivalent programme using
ByteString
s could finish in time. - Not thatByteString
s are per se faster thanText
, but since the input must be converted to the internal representation ofText
whileByteString
takes it as is, that might make a difference. Another possible reason thatByteString
s might be faster - if the testing machines have 32-bit GHCs - would be that text's fusion at least used to need more registers than generally available on 32 bit architectures to get full profit [a long time ago, in the days of text-0.5 to text-0.7, on my 32-bit box, bytestring used to be quite a bit faster, no idea whether that still holds for newer text versions].Okay, since user5402 has verified that the naïve algorithm is fast enough in C, I've gone ahead and wrote an implementation of the naïve algorithm using
ByteString
s{-# LANGUAGE BangPatterns #-} module Main (main) where import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Unsafe as U import Control.Monad import Data.Word main :: IO () main = do cl <- C.getLine case C.readInt cl of Just (cases,_) -> replicateM_ cases (C.getLine >>= print . similarity) Nothing -> return () -- Just to keep the condition readable. (?) :: B.ByteString -> Int -> Word8 (?) = U.unsafeIndex similarity :: B.ByteString -> Int similarity bs | len == 0 = 0 | otherwise = go len 1 where !len = B.length bs go !acc i | i < len = go (acc + prf 0 i) (i+1) | otherwise = acc prf !k j | j < len && bs ? k == bs ? j = prf (k+1) (j+1) | otherwise = k
and compared it to the OP's
Text
version on some bad cases. On my box, that is more than four times faster than theText
version, so it'd be interesting whether that's fast enough (the C version is another 4.5 times faster, so it may well not be).However, I consider it more likely that the time limit is exceeded due to using the naïve algorithm that has quadratic worst-case behaviour. Probably there are test cases that evoke the worst-case for the naïve algorithm.
So the solution would be to use an algorithm that scales better, optimally linear. One linear algorithm to compute the similarity of a string is the Z-algorithm.
The idea is simple (but, like most good ideas, not easy to have). Let us call a (non-empty) substring that is also a prefix of the string a prefix-substring. To avoid recomputation, the algorithm uses a window of the prefix-substring starting before the currently considered index that extends farthest to the right (initially, the window is empty).
Variables used and invariants of the algorithm:
i
, the index under consideration, starts at 1 (for 0-based indexing; the entire string is not considered) and is incremented tolength - 1
left
andright
, the first and last index of the prefix-substring window; invariants:
left < i
,left <= right < length(S)
, eitherleft > 0
orright < 1
,- if
left > 0
, thenS[left .. right]
is the maximal common prefix ofS
andS[left .. ]
,- if
1 <= j < i
andS[j .. k]
is a prefix ofS
, thenk <= right
- An array
Z
, invariant: for1 <= k < i
,Z[k]
contains the length of the longest common prefix ofS[k .. ]
andS
.The algorithm:
- Set
i = 1
,left = right = 0
(any values withleft <= right < 1
are allowed), and setZ[j] = 0
for all indices1 <= j < length(S)
.- If
i == length(S)
, stop.- If
i > right
, find the lengthl
of the longest common prefix ofS
andS[i .. ]
, store it inZ[i]
. Ifl > 0
we have found a window extending farther right than the previous, then setleft = i
andright = i+l-1
, otherwise leave them unchanged. Incrementi
and go to 2.Here
left < i <= right
, so the substringS[i .. right]
is known - sinceS[left .. right]
is a prefix ofS
, it is equal toS[i-left .. right-left]
.Now consider the longest common prefix of
S
with the substring starting at indexi - left
. Its length isZ[i-left]
, henceS[k] = S[i-left + k]
for0 <= k < Z[i-left]
and
S[Z[i-left]] ≠ S[i-left+Z[i-left]]
. Now, ifZ[i-left] <= right-i
, theni + Z[i-left]
is inside the known window, thereforeS[i + Z[i-left]] = S[i-left + Z[i-left]] ≠ S[Z[i-left]] S[i + k] = S[i-left + k] = S[k] for 0 <= k < Z[i-left]
and we see that the length of the longest common prefix of
S
andS[i .. ]
has lengthZ[i-left]
. Then setZ[i] = Z[i-left]
, incrementi
, and go to 2.Otherwise,
S[i .. right]
is a prefix ofS
and we check how far it extends, starting the comparison of characters at the indicesright+1
andright+1 - i
. Let the length bel
. SetZ[i] = l
,left = i
,right = i + l - 1
, incrementi
, and go to 2.Since the window never moves left, and the comparisons always start after the end of the window, each character in the string is compared at most once successfully to an earlier character in the string, and for each starting index, there is at most one unsuccessful comparison, therefore the algorithm is linear.
The code (using
ByteString
out of habit, ought to be trivially portable toText
):{-# LANGUAGE BangPatterns #-} module Main (main) where import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Unsafe as U import Data.Array.ST import Data.Array.Base import Control.Monad.ST import Control.Monad import Data.Word main :: IO () main = do cl <- C.getLine case C.readInt cl of Just (cases,_) -> replicateM_ cases (C.getLine >>= print . similarity) Nothing -> return () -- Just to keep the condition readable. (?) :: B.ByteString -> Int -> Word8 (?) = U.unsafeIndex -- Calculate the similarity of a string using the Z-algorithm similarity :: B.ByteString -> Int similarity bs | len == 0 = 0 | otherwise = runST getSim where !len = B.length bs getSim = do za <- newArray (0,len-1) 0 :: ST s (STUArray s Int Int) -- The common prefix of the string with itself is entire string. unsafeWrite za 0 len let -- Find the length of the common prefix. go !k j | j < len && (bs ? j == bs ? k) = go (k+1) (j+1) | otherwise = return k -- The window with indices in [left .. right] is the prefix-substring -- starting before i that extends farthest. loop !left !right i | i >= len = count 0 0 -- when done, sum | i > right = do -- We're outside the window, simply -- find the length of the common prefix -- and store it in the Z-array. w <- go 0 i unsafeWrite za i w if w > 0 -- We got a non-empty common prefix and a new window. then loop i (i+w-1) (i+1) -- No new window, same procedure at next index. else loop left right (i+1) | otherwise = do -- We're inside the window, so the substring starting at -- (i - left) has a common prefix with the substring -- starting at i of length at least (right - i + 1) -- (since the [left .. right] window is a prefix of bs). -- But we already know how long the common prefix -- starting at (i - left) is. z <- unsafeRead za (i-left) let !s = right-i+1 -- length of known prefix starting at i if z < s -- If the common prefix of the substring starting at -- (i - left) is shorter than the rest of the window, -- the common prefix of the substring starting at i -- is the same. Store it and move on with the same window. then do unsafeWrite za i z loop left right (i+1) else do -- Otherwise, find out how far the common prefix -- extends, starting at (right + 1) == s + i. w <- go s (s+i) unsafeWrite za i w loop i (i+w-1) (i+1) count !acc i | i == len = return acc | otherwise = do n <- unsafeRead za i count (acc+n) (i+1) loop 0 0 1
相关问答
更多-
从性能的角度来看,HackerRank问题通常非常苛刻。 首先尝试的显而易见的事情是使用瞬态向量,看看是否有帮助。 我试过这个: (let [in (clojure.string/split (slurp *in*) #"\s") tests (first in) input-data (map #(Integer/parseInt %) (rest in))] (loop [v (transient []) d input-data] ( ...
-
字符串块格式化挑战(String block formatting challenge)[2022-09-20]
这里有一个awk脚本,它可以帮助你最大限度地完成任务。 将Lon,date,M0等转换为练习: curl --silent http://earthquake.usgs.gov/earthquakes/eqinthenews/2010/uu00002715/uu00002715_gcmt.php | awk ' BEGIN { FS = "[,:;= ]+" OFS = "^" } // {process=1} /<\/pre>/ { ...
-
因为我没有看到一种不吉利的方式。 也许这种冒险的方式可能会有所帮助 string input = @"WwwAuthenticate: Bearer realm=""https://somesite/auth"",service=""some site"",scope=""some, scope"""; var dict = Regex.Matches(input, @"[\W]+(\w+)=""(.+?)""").Cast
() .ToDictionary(x => x.G ... -
首先,在F中生成K的所有因子。这可以在O(√K)时间内天真地完成。 对于每个不友好的数字Ui,计算gcd(K,Ui)并将其存储在集合S中。对于N个坏数字,需要O(NlogK)。 最后,我们通过找出F中的因子数来计算答案,这些因子是S中没有数字的因子。因为两组最多包含| F |。 数字,那么这需要O(| F | ^ 2)时间。 First, generate all the factors of K in F. This can be done naively in O(√K) time. For each ...
-
你不能用第一个额外的球获得9个针脚,然后用第二个额外的球获得6个针脚,因为当你倒入第二个额外的球时只剩下1个针脚。 You cannot get 9 pins with the first extra ball and then 6 pins with the second extra ball because there is only 1 pin left standing when you bowl the second extra ball.
-
这个解决方案对于Max Counters编码挑战有什么问题(What's wrong with this solution for Max Counters codility challenge)[2023-08-14]
一个问题在这里: counters[a - 1] += 1 if counters[a - 1] < last_update: counters[a - 1] = last_update + 1 如果counters[a - 1]是last_update - 1呢? One problem is here: counters[a - 1] += 1 if counters[a - 1] < last_update: counters[a - 1] = last_update + 1 wh ... -
针对InterviewStreet字符串相似度挑战的Haskell解决方案(Haskell solution for InterviewStreet String Similarity challenge)[2021-11-16]
和user5402一样,我很好奇是否等效(对于某些等价的值)C程序会在时限内完成还是超时。 如果愿意的话,看看使用ByteString的等效程序是否可以及时完成将会很有趣。 - 并不是ByteString本身比Text更快,但由于输入必须转换为Text的内部表示,而ByteString按原样转换,这可能会有所不同。 ByteString可能更快的另一个可能原因 - 如果测试机器具有32位GHC - 那么文本的融合至少需要比32位架构上通常可用的寄存器更多才能获得全部利润[很久以前在text-0.5 to t ... -
使用HashSet 。 它提供了交叉路口的功能。 list1 // your 1st list list2 // your second list Set
s1 = new HashSet (); s1.addAll(list1); // add your values from list 1 Set s2 = new HashSet (); s2.addAll(list2); // add your values from list 2 Set ... -
算法(或指向文献的指针)寻求字符串处理挑战(Algorithm (or pointer to literature) sought for string processing challenge)[2022-10-09]
抄袭检测的一般方法是将学生的文本附加到由两者中没有出现的字符分隔的源文本中,然后构建后缀树或后缀数组。 这将允许您在线性时间中查找学生文本中也出现在源文本中的大子串。 我觉得很难更具体,因为我不明白你对分数的解释 - 上面的方法对于找到学生作品中最长的延伸是很好的,这是一个确切的引用,但我不明白你的N - 是它是构建学生文本所需的源文本的不同部分的数量? 如果是这样,可能存在动态编程方法。 在步骤k,我们计算出构造学生文本的前k个字符所需的源文本的最少数量的不同部分。 使用仅从源文本或其他方式构建的后缀数组 ... -
由于这是一个编码挑战,我不会用代码回答,相反,这是你应该如何处理它: 声明另一个数组 开始逐个元素地迭代第一个数组 如果元素是4,则断开循环 如果元素不是4,则将其添加到另一个数组中 最后,第二个数组应该包含前4个之前存在的所有元素。 As it's a coding challenge, I won't answer with code, instead, here's how you should approach it: Declare another array Start iterating fi ...