2.5 cache

This exercise is optional. Refer to the exercise policy for details.
Implement a simulator for a cache.
Here’s my advice for a design:
Your program should expect any number of simulations on standard input. Each simulation starts with a single line with four numbers on it: the number of addresses, the number of sets, the number of lines per set, and then the size of lines (in addresses). Each simulation then consists of any number of addresses (numbers smaller than the number of addresses) delimited by newline characters (\n) on standard input and display the message Hit! :D\n or Miss! :P\n on standard output for each address. A simulation ends with the input q. After a simulation ends, if the input to the program ends, then the program should exit without errors.
Next slowly make it more complicated by controling what kinds of simulations are allowed.First, you can implement the exercise so the cache parameters are fixed and cannot be changed by the input (although still require it to be there!). Second, you can implement the cache so that you do not support set-associativity, but support arbitrary parameters. Third, if you do support set-associativity, you don’t have to implement LRU replacement, but can implement any convenient policy. Finally, you can implement set-associativity and LRU replacement.