Advertisement
Guest User

Untitled

a guest
Jun 12th, 2016
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Eiffel 21.21 KB | None | 0 0
  1. note
  2.   description: "Objects that represent ADT MAP:KEY x VALUE."
  3.   author: "Przemyslaw Pawluk"
  4.   date: "2013 May 9"
  5.   version: 1.0
  6.  
  7. class
  8.     MY_MAP[K,V]
  9. create
  10.    make
  11.  
  12.  
  13. feature {none}  --Representation
  14.  
  15. list:LINKED_LIST[ITEM[K,V]]
  16.  
  17.  
  18. count: INTEGER -- counter
  19.  
  20.  
  21. feature {ANY}
  22.  
  23.     make
  24.         --creates all required variables
  25.     do
  26.  
  27.     create list.make
  28.     count:=0;
  29.  
  30.     ensure
  31.  
  32.          count = 0
  33.          list.is_empty
  34.     end
  35.  
  36.  
  37.     put(key: K; value: V)
  38.         --add the give <key, value> to the map. If the key already exist then the value is updated.
  39.  
  40.         require
  41.           key_Nvoid: key /= void
  42.           val_Nvoid: value /= void
  43.  
  44.         local
  45.             i, j, capacity: INTEGER
  46.             exit: BOOLEAN
  47.             item: ITEM[K,V]
  48.         do
  49.  
  50.  
  51.            create item.make (key,value)
  52.             capacity := count + 1
  53.             i := 1
  54.             j := count
  55.  
  56. --         if the key exist find the key. If not, simply add the key and val to the map.
  57.            if has_key(key)
  58.            then
  59.                 from
  60.                 list.start
  61.                 invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  62.                            (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  63.                            (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  64. --                          NOT CODED: for all N elements in the map, the elements
  65. --                          from 1 to i-1 does dont contain the key.
  66.  
  67.                 until
  68. --                 i starts at 1. Thus this condition will be true when i >= capacity (N + 1) or the key has been found, and exit the loop.                
  69.                    i >= capacity or exit
  70.                 loop
  71.  
  72.  
  73.                     if   list.i_th (i).getkey ~ (key)
  74.                     then
  75.                         list.go_i_th (i)
  76.                         list.replace (item)
  77.  
  78.                         exit := true -- exit loop
  79.  
  80.  
  81.                     end
  82.  
  83.                     i := i + 1
  84.                     j := j - 1
  85.                     variant j
  86.  
  87.                 end
  88.  
  89.             else
  90.  
  91.                   list.extend (item)
  92.                   count := count + 1
  93.             end
  94.  
  95.         ensure
  96. --      ensure the key was added
  97.         putWorked:  exist1 (key, value)
  98.  
  99.  --     if the key existed current count must equal old count
  100.  --     if the key did not exist then current count must equal old count + 1
  101.         correct_count: ( old current.has1(key) and count = old count) xor
  102.                               (not old current.has1(key) and count = old count + 1)
  103.         end
  104.  
  105.  
  106.     get(key:K):V
  107.     -- the key must exist in the map. return the value associated with the given key.
  108.     require
  109.         Key /= void
  110.         has_key(key) -- PLEASE READ: The proffesor stated in class, if the key dosent exist, we can leave the resposibility to the user
  111.                      --              by adding a requirement where the key passed must exist. thus, it is the users resposibility
  112.                      --              to check if the key exist before he runs this method.
  113.  
  114.  
  115.     local
  116.          i,j, capacity : INTEGER
  117.          exit : BOOLEAN
  118.          item: ITEM[K,V]
  119.          value: V
  120.          value_void :  detachable V
  121.  
  122.     do
  123.             capacity := count + 1
  124.             i := 1
  125.             j := count
  126.  
  127.             from
  128.                 list.start
  129.             invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  130.                        (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  131.                        (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  132. --                      not coaded: for all N elements in the map, the elements
  133. --                      from 1 to i-1 does dont contain the key.
  134. --                         
  135.             until
  136. --              i starts at 1. Thus this condition will be true when i >= capacity (N + 1) or the key has been found, and exit the loop.
  137.                 i >= capacity or exit
  138.             loop
  139.                 if   list.i_th (i).getkey ~ key
  140.                 then
  141.  
  142.                     value := list.i_th (i).getvalue
  143. --                  so we dont return the reference                    
  144.                     result := value.deep_twin
  145.  
  146.                     exit := true -- exit loop
  147.  
  148.                 end
  149.  
  150.                 i := i + 1
  151.                 j := j - 1
  152.  
  153.                 variant j
  154. --             
  155.                 end
  156.  
  157. --          PLEASE READ:  this is how I would make my method return a void value if required.
  158.  
  159. --          if (not exit)
  160. --          then
  161.  
  162. --              result := value_void
  163. --          end
  164.  
  165.  
  166.         ensure
  167.  
  168.             no_change_attributes: no_change_attributes (old count, old key_set, old value_set)
  169.  
  170.             correct_output: exist1(key, result)
  171. --          PLEASE READ: if void is allowed to be returned then my method would have the following ensure:
  172. --          correct_output: ( not current.has_key(key) and result = void) xor
  173. --                              ( current.has_key(key) and exist1(key, result))    
  174.  
  175.     end
  176.  
  177.     remove(key:K)
  178. --  given key is removed from the map.
  179.     require
  180.         void_key:  key /= void
  181.  
  182.     local
  183.     i,j, capacity : INTEGER
  184.     stop: BOOLEAN
  185.  
  186.     do
  187.         capacity := count + 1
  188.         i := 1
  189.         j := count
  190.  
  191.  
  192.             from
  193.                 list.start
  194.             invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  195.                        (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  196.                        (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  197. --                      not coaded: for all N elements in the map, the elements
  198. --                      from 1 to i-1 does dont contain the key.
  199. --                         
  200.             until
  201. --              i starts at 1. Thus this condition will be true when i >= capacity (N + 1) or the key has been found, and exit the loop.               
  202.                 i >= capacity or stop
  203.             loop
  204.                 if
  205.                     list.i_th (i).getkey ~ key
  206.                 then
  207.                     list.go_i_th (i)
  208.                     list.remove
  209. --                  one item has been removes thus the map count must decrement by 1
  210.                     count := count - 1
  211.                     stop := true -- exit loop
  212.                 end
  213.                 i := i + 1
  214.                 j := j - 1
  215.                 variant j
  216.  
  217. --          end
  218.  
  219.         end
  220.  
  221.         ensure
  222. --          1) if the key existed in the map ensure the count has been decrented by 1 and the key has actualy been removed
  223. --          2) if the key does not exist ensure no changes have been made to the map.
  224. --          3) "xor" only one of conditions 1 or 2  can be true at the same time.
  225.            correct_remove: old has_key (key) and old count - 1 = count and not has_key(key) xor
  226.            not old has_key(key) and no_change_attributes (old count, old key_set, old value_set)
  227.  
  228.  
  229.  
  230.  
  231.  
  232.     end
  233.  
  234.     has(key:K; val:V):BOOLEAN
  235.     -- returns true if the given combination of the key and value exist in the map
  236.     -- does not guarantee there exist only one combination of the given key and value
  237.     require
  238.         void_key: key /= void
  239.         void_val: val /= void
  240.  
  241.  
  242.     local
  243.         i,j, capacity : INTEGER
  244.         return : BOOLEAN
  245.     do
  246.         capacity := count + 1
  247.         i := 1
  248.         j := count
  249.  
  250.         from
  251.              list.start
  252.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  253.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  254.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  255. --                  not coaded: for all N elements in the map, the elements
  256. --                  from 1 to i-1 does dont contain the given combination of key and value.
  257.         until
  258. --           i starts at 1. Thus this condition will be true when i >= capacity (N + 1) or the combination of the key and value has been found. exit loop.         
  259.              i >= capacity or return
  260.         loop
  261. --          check if the given combination of key and value match the key and value at the i th location
  262.             if   (list.i_th (i).getkey ~ key) and (list.i_th (i).getvalue ~ val)
  263.             then
  264.                return := true
  265.             end
  266.             i := i + 1
  267.             j := j - 1
  268.             variant j
  269.         end
  270.  
  271.  
  272.  
  273.         result := return
  274.         ensure
  275. --          ensure no changes has been made to the map
  276.             no_change: no_change_attributes (old count, old key_set, old value_set)
  277.  
  278. --          use exist(K,V) to ensure that has(K,V) returned the correct result
  279.             correct_out: result = exist(key, val)
  280.  
  281.     end
  282. --------------------------------------------------------------------------------------------------
  283.     key_set:SET[K]
  284.     -- returns a set of key values from the map
  285.     local
  286.         set: LINKED_SET[K]
  287.         i,j, capacity : INTEGER
  288.     do
  289.         capacity := count + 1
  290.         i := 1
  291.         j := count
  292.         create set.make
  293.         from
  294.             list.start
  295.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  296.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  297.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(N - N) is alwais = N
  298.         until
  299. --           i starts at 1. Thus this condition will be true when i >= capacity (N + 1)
  300.             i >= capacity
  301.         loop
  302. --          add a copy of the key to the set
  303.             set.extend (list.i_th (i).getkey.deep_twin)
  304.  
  305.             i := i + 1
  306.             j := j - 1
  307.         variant j
  308.  
  309.         end
  310.         result := set
  311.  
  312.  
  313.         ensure
  314. --      ensure all the keys from the map where added to the list           
  315.         containAllKey_set:  current.key_check(result)
  316.  
  317. --      ensure no changes where made to the map
  318.         no_change: no_change_attributes (old count, old key_set, old value_set)
  319.  
  320.     end
  321.  
  322.     value_set:SET[V]
  323.     -- returns a set of values from the map
  324.  
  325.     local
  326.         i,j, capacity : INTEGER
  327.         set: LINKED_SET[V]
  328.  
  329.     do
  330.  
  331.         capacity := count + 1
  332.         i := 1
  333.         j := count
  334.         create set.make
  335.         from
  336.             list.start
  337.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  338.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  339.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(N - N) is alwais = N
  340.         until
  341. --           i starts at 1. Thus this condition will be true when i >= capacity (N + 1)        
  342.             i >= capacity
  343.         loop
  344. --              add a copy of the key to the set           
  345.                 set.extend (list.i_th (i).getvalue.deep_twin)
  346.                 i := i + 1
  347.                 j := j - 1
  348.         variant j
  349.  
  350.         end
  351.  
  352.         result := set
  353.  
  354.  
  355.  
  356.         ensure
  357. --      ensure all the values from the map where added to the list.            
  358.         no_change: no_change_attributes (old count, old key_set, old value_set)
  359. --      ensure no changes where made to the map
  360.         containAllVal_set:  current.val_check(result)
  361.  
  362.     end
  363.  
  364. feature --Quantifiers
  365.  
  366.     exist(key:K; val:V):BOOLEAN
  367.     --checks if given key/value combination exist in the map
  368.    -- does not guarantee there exist only one combination of the given key and value
  369.     require
  370.         key /= void
  371.         val /= void
  372.     local
  373.         i,j, capacity: INTEGER
  374.         exit: BOOLEAN
  375.         return: BOOLEAN
  376.     do
  377.         capacity := count + 1
  378.         i := 1
  379.         j := count
  380.         return := false
  381.         from
  382.             list.start
  383.  
  384.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  385.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  386.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  387. --                  not coaded: for all N elements in the map, the elements
  388. --                  from 1 to i-1 does dont contain the given combination of key and value.
  389.  
  390.         until
  391. --          i starts at 1. Thus this condition will be true when i >= capacity (N + 1) or the combination of the key and value has been found. exit loop.                  
  392.             i >= capacity or exit
  393.         loop
  394. --          check if the given combination of key and value match the key and value at the i th location
  395.             if (list.i_th (i).getkey ~ key) and (list.i_th (i).getvalue ~ val)
  396.             then
  397.                 return := true
  398.                 exit := true
  399.             end
  400.             i := i + 1
  401.             j := j - 1
  402.             variant j
  403.         end
  404.         result := return
  405.  
  406.         ensure
  407. --      ensure no changes where made to the map            
  408.          no_change: no_change_attributes (old count, old key_set, old value_set)
  409.     end
  410. feature
  411.     exist1(key:K; val:V):BOOLEAN
  412.     --checks if there is only one pair with given key/value combination
  413.     require
  414.         key /= void
  415.         val /= void
  416.     local
  417.         i,j, capacity: INTEGER
  418.         count_in: INTEGER
  419.     do
  420.         capacity := count + 1
  421.         i := 1
  422.         j := count
  423.         from
  424.             list.start
  425.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  426.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  427.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  428.  
  429.         until
  430. --          i starts at 1. Thus this condition will be true when i >= capacity (N + 1)         
  431.             i >= capacity
  432.         loop
  433. --          check if the given combination of key and value match the key and value at the i th location           
  434.             if list.i_th (i).getkey ~ key and list.i_th (i).getvalue ~ val
  435.             then
  436. --              keep count of how many times this block is accessed
  437.                 count_in := count_in + 1
  438.             end
  439.  
  440.             i := i + 1
  441.             j := j - 1
  442.             variant j
  443.         end
  444.  
  445. --      if count = 1 then the block was only accesed once and there is only one matching key and value in the map      
  446.         if count_in = 1
  447.          then
  448.             result := true
  449.         else
  450.             result := false
  451.         end
  452.  
  453.         ensure
  454. --          ensure no changes have been made to the map
  455.             no_change: no_change_attributes (old count, old key_set, old value_set)
  456.     end
  457.  
  458.     has1(key:K):BOOLEAN
  459.  
  460.     --checks if there is only one key with given value
  461.     require
  462.         key /= void
  463.     local
  464.         i,j, capacity: INTEGER
  465.         count_in: INTEGER
  466.     do
  467.         capacity := count + 1
  468.         i := 1
  469.         j := count
  470.         count_in := 0
  471.         from
  472.             list.start
  473.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  474.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  475.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  476.  
  477.         until
  478. --          i starts at 1. Thus this condition will be true when i >= capacity (N + 1)
  479.             i >= capacity
  480.         loop
  481.  
  482.             if key ~ list.i_th (i).getkey
  483.              then
  484. --              keep count of how many times this block is accessed                
  485.                 count_in := count_in + 1
  486.             end
  487.  
  488.             i := i + 1
  489.             j := j - 1
  490.             variant j
  491.  
  492.         end
  493. --      if count = 1 then the block was only accesed once and there is only one matching key in the map        
  494.         if (count_in = 1)
  495.          then
  496.             result := true
  497.         else
  498.             result := false
  499.         end
  500.  
  501.  
  502.         ensure
  503.             no_change: no_change_attributes (old count, old key_set, old value_set)
  504.     end
  505. --------------------------------------------------------------------------------------------------------
  506. --------------------------------------------------------------------------------------------------------
  507. feature -- map method's testers for ensure
  508.     has_key(key:K):BOOLEAN
  509. --  checkes if the given key is in the map
  510.     require
  511.         key /= void
  512.     local
  513.         i,j, capacity: INTEGER
  514.         return : BOOLEAN
  515.     do
  516.         capacity := count + 1
  517.         i := 1
  518.         j := count
  519.         return := false
  520.         from
  521.             list.start
  522.  
  523.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  524.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  525.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  526. --                  not coaded: for all N elements in the map, the elements
  527. --                  from 1 to i-1 does dont contain the given combination of key and value.
  528.         until
  529. --          i starts at 1. Thus this condition will be true when i >= capacity (N + 1). exit loop          
  530.                i >= capacity
  531.         loop
  532.  
  533.             if (list.i_th (i).getkey ~ key)
  534.             then
  535.                  return := true
  536.             end
  537.                 i := i + 1
  538.                 j := j - 1
  539.             variant j
  540.         end
  541.  
  542.             result := return
  543.         ensure
  544. --          no changes have been made to the map            
  545.             no_change: no_change_attributes (old count, old key_set, old value_set)
  546.     end
  547. feature{MY_MAP}
  548.     key_check(set1: SET[K]):BOOLEAN
  549.     -- to check if every key is in the set
  550.  
  551.     require
  552. --      key_same_size: set1.count = count
  553.     local
  554.         i,j, capacity: INTEGER
  555.         exit: BOOLEAN
  556.     do
  557.         capacity := count + 1
  558.         i := 1
  559.         j := count
  560.         exit := false
  561.  
  562.  
  563.         from
  564.             list.start
  565.         invariant ((i <= capacity) and -- let N be the number of elements in the map. and i be the number of iterations. for all i such that i(1), i(2)... i(N). i is always <= N
  566.                    (j >= 0) and -- for all j such that j(N - 1), j(N - 2)... j(0). j is always >= 0
  567.                    (i + j = capacity))-- for all i and j such that j(N - 1)+ i(1), i(2) + j(N - 2)... i(N)+j(0) is alwais = N
  568. --                 not coaded:  let i be the location of the present iteration. Then for all N elements in the map and  K be the elements in the Set, such that
  569. --                  N(1) = K(1), N(2) = K(2)..... N(i-1) = k(i - 1).
  570.  
  571.         until
  572.             i >= capacity or exit
  573.         loop
  574.             set1.compare_objects
  575.  
  576. --          if any items in the set dont match the item in the list then we exit loop          
  577.             if set1.has (list.i_th (i).getkey)
  578.             then
  579.             exit := false
  580.             else
  581.             exit := true
  582.             end
  583.             i := i + 1
  584.             j := j - 1
  585.             variant j
  586.         end
  587.         -- if exit is true, loop was exited
  588.         -- one key of the list is not in the set, result := false      
  589.         result := not exit
  590.  
  591.  
  592.         ensure
  593.          no_change: no_change_attributes (old count, old key_set, old value_set)
  594.  
  595.     end
  596.  
  597.      val_check(set1: SET[V]):BOOLEAN
  598.     -- to check if every val is in the set
  599.     require
  600. --      val_size: set1.count <= count -- SET does not allow duplicates, so  ensure that set count is always <= map count
  601.     local
  602.         i,j, capacity: INTEGER
  603.         exit: BOOLEAN
  604.     do
  605.         capacity := count + 1
  606.         i := 1
  607.         j := count
  608.  
  609.         from
  610.             list.start
  611.  
  612.         invariant ((i <= capacity) and -- let K be the number of elements in the set. and i be the number of iterations 1 to K. for all i such that i(1), i(2)... i(K). i is always <= K <=N
  613.                    (j >= 0) and -- for all j such that j(K - 1), j(K - 2)... j(K - K). j is always >= 0
  614.                    (i + j = capacity))-- for all i and j such that j(K - 1)+ i(1), i(2) + j(K - 2)... i(K)+j(K-K) is alwais = K
  615. --                  let i be the location of the present iteration from 1 to K.  K being the # of set elements and N the number of
  616. --                  elements in the map, such that N(1) = K(1), N(2) = K(2)..... N(i-1) = k(i - 1).
  617. --                         
  618.         until
  619.             i >= capacity or exit
  620.         loop
  621.  
  622.             set1.compare_objects
  623.             if set1.has (list.i_th (i).getvalue)
  624.             -- if the value value is not in the set. exit the loop.
  625.             then
  626.             exit := false
  627.             else
  628.             exit := true
  629.             end
  630.             i := i + 1
  631.             j := j - 1
  632.             variant j
  633.         end
  634.         result := not exit
  635.         -- if exit is true, loop was exited
  636.         -- one key of the list is not in the set, result := false
  637.  
  638.         ensure
  639.          no_change: no_change_attributes (old count, old key_set, old value_set)
  640.  
  641.     end
  642.  
  643.     no_change_attributes( old_count : INTEGER
  644.                     ; old_keys : SET[K]; old_values : SET[V]) : BOOLEAN
  645.          do
  646.             Result := count = old_count and deep_equal(key_set, old_keys)
  647.                   and deep_equal(value_set, old_values)
  648.  
  649.          end
  650.  
  651.  
  652. invariant
  653.     count: count>=0
  654.     correct_count: count = list.count
  655.     key_set.count = count
  656.  
  657.     -- for all elements in the list there exist a unique key
  658.     unique_keys: across list as l all
  659.                     has1(l.item.getkey)
  660.      end
  661.  
  662. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement