fork(1) download
  1. # @file pendulum.rb
  2. # Question-8 from some problem set.
  3. # @date 03/28/2026
  4.  
  5. # Rearrange the word so the character with the smallest ASCII value
  6. # is placed at the center, the second smallest to its right and the
  7. # third to its left and so on.
  8. #
  9. # Example-1: In : COMPUTER
  10. # Out: TPMCEORU
  11. #
  12. # Example-2: In : SCIENCE
  13. # Out: SIECCEN
  14. #
  15. # The problem specifies characters should be rearranged by invoking
  16. # the function 'int minimumCharIndex(String str)'.
  17.  
  18. def pendulum_0(s)
  19. def minimum_char_index(s)
  20. s.index(s.each_byte.min.chr) # faster than each_char.min
  21. end
  22.  
  23. s = s.dup
  24. n = s.size
  25. m = (n+1) / 2
  26. r = []
  27. n.times do |i|
  28. j = i / 2
  29. k = minimum_char_index(s)
  30. r[i.even? ? m-j-1 : m+j] = s.slice!(k)
  31. end
  32. r.join
  33. end
  34.  
  35. # Breaking the rules a bit.
  36.  
  37. def pendulum_0_1(s)
  38. def minimum_index(a, first, last)
  39. subarray = a[first...last]
  40. subarray.index(subarray.min) + first
  41. end
  42.  
  43. s = s.bytes
  44. n = s.size
  45. m = (n+1) / 2
  46. r = []
  47. n.times do |i|
  48. j = i / 2
  49. k = minimum_index(s, i, n)
  50. r[i.even? ? m-j-1 : m+j] = s[k]
  51. s[k] = s[i]
  52. end
  53. r.map(&:chr).join
  54. end
  55.  
  56. def pendulum_0_2(s)
  57. def swap(a, i, j)
  58. a[i], a[j] = a[j], a[i] if i != j
  59. end
  60.  
  61. def minimum_index(a, first, last)
  62. subarray = a[first...last]
  63. subarray.index(subarray.min) + first
  64. end
  65.  
  66. def selectsort!(a)
  67. (a.size-1).times do |i|
  68. swap(a, i, minimum_index(a, i, a.size))
  69. end
  70. a
  71. end
  72.  
  73. n = s.size
  74. m = (n+1) / 2
  75. r = []
  76. selectsort!(s.bytes).each_with_index do |x, i|
  77. j = i / 2
  78. r[i.even? ? m-j-1 : m+j] = x
  79. end
  80. r.map(&:chr).join
  81. end
  82.  
  83. # Breaking the rules a bit more.
  84.  
  85. def pendulum_1(s)
  86. n = s.size
  87. m = (n+1) / 2
  88. r = []
  89. s.chars.sort!.each_with_index do |x, i|
  90. j = i / 2
  91. r[i.even? ? m-j-1 : m+j] = x
  92. end
  93. r.join
  94. end
  95.  
  96. def pendulum_2(s)
  97. r = []
  98. s.chars.sort!.each_with_index do |x, i|
  99. r.public_send(i.even? ? :unshift : :push, x)
  100. end
  101. r.join
  102. end
  103.  
  104. def pendulum_3(s)
  105. t = s.chars.sort!
  106. l, r = t.drop(1).partition.each_with_index{|_, i| i.odd?}
  107. (l.reverse + t.take(1) + r).join
  108. end
  109.  
  110. def pendulum_4(s)
  111. l, r = (1...s.size).partition{|i| i.even?}
  112. s.chars.sort!.values_at(*l.reverse, 0, *r).join
  113. end
  114.  
  115. # Main.
  116.  
  117. def test(f)
  118. ss = ["", "a", "bca", "computer", "science"]
  119. rs = ["", "a", "cab", "tpmceoru", "sieccen"]
  120.  
  121. ss.zip(rs) do |s, r|
  122. s = f.call(s)
  123. if s != r
  124. puts ".Failed: expected `#{r}' got `#{s}'"
  125. return
  126. end
  127. end
  128. puts ".Passed"
  129. end
  130.  
  131. def time(f)
  132. def choices(pool, n)
  133. n.times.map{pool.sample}
  134. end
  135.  
  136. symbols = ('a'..'z').to_a
  137. elapsed = 0
  138.  
  139. 12.times do |i|
  140. s = choices(symbols, 2**i).join
  141. t = Time.now
  142. f.call(s)
  143. elapsed += Time.now - t
  144. end
  145. printf(".Elapsed: %.6fs\n", elapsed)
  146. end
  147.  
  148. fs = [
  149. :pendulum_0,
  150. :pendulum_0_1,
  151. :pendulum_0_2,
  152. :pendulum_1,
  153. :pendulum_2,
  154. :pendulum_3,
  155. :pendulum_4
  156. ]
  157.  
  158. fs.map(&method(:method)).each do |f|
  159. puts f.name
  160. test(f)
  161. time(f)
  162. end
Success #stdin #stdout 0.17s 38624KB
stdin
Standard input is empty
stdout
pendulum_0
.Passed
.Elapsed: 0.072929s
pendulum_0_1
.Passed
.Elapsed: 0.035879s
pendulum_0_2
.Passed
.Elapsed: 0.035047s
pendulum_1
.Passed
.Elapsed: 0.002061s
pendulum_2
.Passed
.Elapsed: 0.003582s
pendulum_3
.Passed
.Elapsed: 0.001762s
pendulum_4
.Passed
.Elapsed: 0.001986s