I have a column vector X of size N-by-1 with two values: 10 and 25. I want to switch those values, i.e. every element with value 10 should become 25 and vice versa.
Pseudo-code:
A = [ 10; 25; 25; 10; 25; 25; 10]
NewNew = find(A == 10)
NewNew2 = find(A == 25)
NewNew3 = [ ];
for NewNew3
if NewNew
NewNew=25
else NewNew2
NewNew2=10
end
I tried this now still no success:
for B = 1:size(A)
if A == 10
A = 25
elseif A == 25
A = 10
end
end
How can I switch values?
If you only have two values, why not subtracting from their addition:
A = 35 - A;
N=10;
X = randi([1 2],N,1);
A = zeros(size(X)); % create output vector
A(X==2)=1; % whenever X==2, set A=1
A(X==1) = 2; % whenever X==1, set A=2
[X A]
ans =
1 2
2 1
2 1
1 2
2 1
1 2
1 2
2 1
2 1
2 1
You can do this with logical indexing. Just make sure to get a separate output vector, as setting X(X==1)=2 will make your whole vector 2, and then calling X(X==2)=1 sets the whole vector to 1. If necessary, use X=A at the end.
Final advice: your for loop needs indexing, which is about as basic as MATLAB goes. You can solve this problem with a for loop, although I'd recommend using logical indexing as per the above. I strongly suggest you to either take a basic course in MATLAB, or read the MathWork's own tutorial on MATLAB.
There are some other options you can consider.
1.) (Irrelevant option. Use ibancg's option, cleaner and faster.)
If you have just those two values, a simpler and faster solution would be to initialize to one of these two numbers and flip just a subset of the numbers:
A = [ 10; 25; 25; 10; 25; 25; 10];
X = ones(size(A)) * 10; % initialize X with 10.
X(A == 10) = 25; % Set values where A is 10 to 25.
2.) (irrelevant, too slow): Another possibility if you know that some numbers will never appear is to use temporary third number and avoid creating a new matrix - operate kind of similar to the typical "swap two numbers" recipe.
A(A == 10) = 1; % Temp value
A(A == 25) = 10;
A(A == 1) = 25;
3.) Finally, the third option would be to save logical matrix and then overwrite A.
Ais10 = A==10;
Ais25 = A==25;
A(Ais10) = 25;
A(Ais25) = 10;
Now, for the benchmarks: I used very simple script, varying N and M.
tic
for i = 1 : M
X1 = randi([1 2],N,1);
... % depends on test cases. Result can be in X or A.
toc
Therefore, it also times randi, but as it is a part of every code it should only mask the relative speed differences, keeping absolute ones the same. Computer is i7 4770k, 32GB RAM.
Row vector has 1000 elements, 1M runs; 100M elements, 10 runs; 1B elements, 1 run; 3B elements, 1 run
Codes that rely on having just 2 values:
1I): 18.3 s; 20.7 s; 20.3 s; 63.6 s
1Z): 33.0 s; 38.2 s; 38.0 s; NA (out of memory)
Code relies on lacking one value that can be used for swap:
2Z): 54.0 s; 60.5 s; 60.0 s; 659 s
Code handles arbitrary data, swapping 2 values.
3A): 45.2 s; 50.5 s; 49.0 s; NA (out of memory)
3Z): 41.0 s; 46.1 s; 45.8 s; NA (out of memory)
So, to summarize, Ibancg's option is much faster and simpler than the rest and should be used if possible (= just those 2 different values in the vector). My 2nd option is far too slow to be relevant. Rather do step by step swap on the vector using any of the general methods. Either general option is fine.
Related
Here is the problem:
data = 1:0.5:(8E6+0.5);
An array of 16 million points, needs to be averaged every 10,000 elements.
Like this:
x = mean(data(1:10000))
But repeated N times, where N depends on the number of elements we average over
range = 10000;
N = ceil(numel(data)/range);
My current method is this:
data(1) = mean(data(1,1:range));
for i = 2:N
data(i) = mean(data(1,range*(i-1):range*i));
end
How can the speed be improved?
N.B: We need to overwrite the original array of data (essentially bin the data and average it)
data = 1:0.5:(8E6-0.5); % Your data, actually 16M-2 elements
N = 1e4; % Amount to average over
tmp = mod(numel(data),N); % find out whether it fits
data = [data nan(1,N-tmp)]; % add NaN if necessary
data2=reshape(data,N,[]); % reshape into a matrix
out = nanmean(data2,1); % get average over the rows, ignoring NaN
Visual confirmation that it works using plot(out)
Note that technically you can't do what you want if mod(numel(data),N) is not equal to 0, since then you'd have a remainder. I elected to average over everything in there, although ignoring the remainder is also an option.
If you're sure mod(numel(data),N) is zero every time, you can leave all that out and reshape directly. I'd not recommend using this though, because if your mod is not 0, this will error out on the reshape:
data = 1:0.5:(8E6+0.5); % 16M elements now
N = 1e4; % Amount to average over
out = sum(reshape(data,N,[]),1)./N; % alternative
This is a bit wasteful, but you can use movmean (which will handle the endpoints the way you want it to) and then subsample the output:
y = movmean(x, [0 9999]);
y = y(1:10000:end);
Even though this is wasteful (you're computing a lot of elements you don't need), it appears to outperform the nanmean approach (at least on my machine).
=====================
There's also the option to just compensate for the extra elements you added:
x = 1:0.5:(8E6-0.5);
K = 1e4;
Npad = ceil(length(x)/K)*K - length(x);
x((end+1):(end+Npad)) = 0;
y = mean(reshape(x, K, []));
y(end) = y(end) * K/(K - Npad);
reshape the data array into a 10000XN matrix, then compute the mean of each column using the mean function.
Problem
Is there a smart way to add arrays/vectors that do not have the same column length, by just adding zeros to columns that are too short? I have additions/subtractions that include multiple variables.
so that:
a=[ 1; 2; 3]; b=[1;5]
a+b=[2; 5; 3]
or:
a-b=[0;-3;3]
instead of:
Error using +
Matrix dimensions must agree.
What I did
b(numel(a),1) = 0;
This works fine, if adding a few variables, but this gets quite annoying while repeating for multiple variables, especially if you don't know which has the longest column. Hence the question if there is an easier fast way for an addition of different column lengths.
Edit
The question really is, if there is a way to automate this for having more than "just a few" variables.
You need to do it more or less manually. For example:
s = [];
s(1,1:numel(a)) = a;
s(2,1:numel(b)) = b; % assigning a row (or column) automatically pads with zeros
% if needed. This works irrespective of which is bigger, a or b
s = sum(s,1); % sum along each column
If you have several variables, it's probably better to put them in a cell array, so you can loop over them:
c = {[1; 2; 3] [1;5] [10 20 30 40]}; % cell array of all "variables"
s = [];
for k = 1:numel(c);
s(k,1:numel(c{k})) = c{k}; % this zero-pads preceding cells' contents if needed
end
s = sum(s,1); % sum along each column
The above may be slow because s is dynamically reallocated. You can preallocate as follows:
c = {[1; 2; 3] [1;5] [10 20 30 40]}; % cell array of all "variables"
m = max(cellfun(#numel, c)); % maximum vector size
s = zeros(numel(c), m); % preallocate and initiallize to zeros
for k = 1:numel(c);
s(k,1:numel(c{k})) = c{k}; % some entries maybe be left as zero
end
s = sum(s,1); % sum along each column
a=[ 1; 2; 3]; b=[1;5];
if numel(b)~=numel(a)
if numel(b)<numel(a) % If b is shorter, extend it
b = [b; zeros(numel(a)-numel(b),1)];
else % If a is shorter, extend it
a = [a; zeros(numel(b)-numel(a),1)];
end
end
a+b
A=[1, 2, 3]; B=[1,5];
[A,zeros(1,length(B)-length(A))]+[B,zeros(1,length(A)-length(B))]
ans =
2 7 3
[A,zeros(1,length(B)-length(A))]-[B,zeros(1,length(A)-length(B))]
ans =
0 -3 3
Stick them in a function and you are done
I came across a problem from a recent competition.
I was unable to figure out a solution, and no editorial for the question is yet available.
Question Link
I am quoting the problem statement here also in case the link doesn't work.
Find the number of integers n which are greater than or equal to A and less than or equal to B (A<= n <=B) and the decimal representation of 2^n ends in n.
Ex: 2^36 = 68719476736 which ends in “36”.
INPUT
The first line contains an integer T i.e. number of test cases. T lines follow, each containing two integers A and B.
Constraints
1 <= T <= 10^5
A<=B
A,B <= 10^150
OUTPUT
Print T lines each containing the answer to the corresponding testcase.
Sample Input
2
36 36
100 500
Sample Output
1
0
As often happens on programming competitions I have come up with an heuristics I have not proven, but seems plausible. I have written a short program to find the numbers up to 1000000 and they are:
36
736
8736
48736
948736
Thus my theory is the following - each consecutive number is suffixed with the previous one and only adds one digit. Hope this will set you on the right track for the problem. Note that if my assumption is right than you only need to find 150 numbers and finding each consecutive number requires checking 9 digits that may be added.
A general advice for similar problems - always try to find the first few numbers and think of some relation.
Also often it happens on a competition that you come up with a theory like the one I propose above, but have no time to prove it. You can't afford the time to prove it. Simply hope you are right and code.
EDIT: I believe I was able to prove my conjecture above(in fact I have missed some numbers -see end of the post). First let me point out that as v3ga states in a comment the algorithm above works up until 75353432948736 as no digit can be prepended to make the new number "interesting" as per the definition you give. However I completely missed another option - you may prepend some number of 0 and then add a non-zero digit.
I will now proof a lemma:
Lemma: if a1a2...an is an interesting number and n is more than 3, then a2...an also is interesting.
Proof:
2a1a2...an = 2a1*10n - 1*2a2a2...an
Now I will prove that 2a1*10n - 1*2a2a2...an is comparable to 2a2a2...an modulo 10n-1.
To do that lets prove that 2a1*10n - 1*2a2a2...an - 2a2a2...an is divisible by 10n-1.
2a1*10n - 1*2a2a2...an - 2a2a2...an =
2a2a2...an * (2a1*10n - 1 - 1)
a2a2...an is more than n-1 for the values we consider.
Thus all that's left to prove to have 10n-1 dividing the difference is that 5n-1 divides 2a1*10n - 1 - 1.
For this I will use Euler's theorem:
2phi(5n-1) = 1 (modulo 5n-1).
Now phi(5n-1) = 4*(5n-2) and for n >= 3 4*(5n-2) will divide a1*10n - 1(actually even solely 10n - 1).
Thus 2a1*10n - 1 gives remainder 1 modulo 5n-1 and so 5n-1 divides 2a1*10n - 1 - 1.
Consequently 10n-1 divides 2a2a2...an * (2a1*10n - 1 - 1) and so the last n - 1 digits of 2a1a2a2...an and 2a2a3a4...an are the same.
Now as a1a2a2...an is interesting the last n digits of 2a1a2a2...an are a1a2a2...an and so the last n-1 digits of 2a2a3a4...an are a2a3a4...an and consequently a2a3a4...an is also interesting. QED.
Use this lemma and you will be able to solve the problem. Please note that you may also prepend some zeros and then add a non-zero number.
In general, you can try solving these problems by finding some pattern in the output. Our team got this problem accepted at the contest. Our approach was to find a general pattern in the values that satisfy the criteria. If you print the first few such digits, then you will find the following pattern
36
736
8736
48736
948736
Thus the next number after 948736 should be of 7 digits and can be any one of 1948736, 2948736, 3948736, 4948736, 5948736, 6948736, 7948736, 8948736, 9948736. Thus check which value is valid and you have the next number. Continuing in this fashion you can back yourself to get all the 150 numbers.
But there is a problem here. There will be some numbers that do not immediately follow from the previous number by appending '1' to '9'. To counter this you can now start appending values from 10 to 99 and now check if there is a valid number or not. If there is still no valid number, then again try appending numbers from 100 to 999.
Now employing this hack, you will get all the 137 values that satisfy the criterion given in the question and easily answer all the queries. For example, working java code that implements this is shown here. It prints all the 137 values.
import java.io.*;
import java.math.*;
import java.util.*;
class Solution
{
public static void main(String[] args)throws java.lang.Exception{
new Solution().run();
}
void run()throws java.lang.Exception{
BigInteger[] powers = new BigInteger[152];
powers[0] = one;
for(int i=1; i<=150; i++){
powers[i] = powers[i-1].multiply(ten);
}
BigInteger[] answers = new BigInteger[152];
answers[2] = BigInteger.valueOf(36);
answers[3] = BigInteger.valueOf(736);
int last = 3;
for(int i=4; i<=150; i++){
int dif = i-last;
BigInteger start = ten.pow(dif-1);
BigInteger end = start.multiply(ten);
while(start.compareTo(end) < 0){
BigInteger newVal = powers[last].multiply(start);
newVal = newVal.add(answers[last]);
BigInteger modPow = pow(two, newVal, powers[i]);
if(modPow.equals(newVal)){
answers[i] = newVal;
System.out.println(answers[i]);
last = i;
break;
}
start = start.add(one);
}
}
}
BigInteger pow(BigInteger b, BigInteger e, BigInteger mod){
if(e.equals(zero)){
return one;
}
if(e.mod(two).equals(zero)){
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
return x;
}else{
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
x = x.multiply(two).mod(mod);
return x;
}
}
BigInteger ten = BigInteger.valueOf(10);
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger two = BigInteger.valueOf(2);
}
This is very interesting property. During the contest, I found that 36 was the only number under 500 checking with python...
The property is : 2^36 last two digits are 36, last three digits are 736, so next number is 736. 2^736 has last three digits as 736, and next number is 8376...
And the series is : 36 , 736 , 8736 , 48736 , 948736 ...
And then started with BigInt class in C++.
But alas there was no time, and 4th problem wasn't solved. But after the contest, we did it in python.
here's link : Ideone it!
def powm(i):
j = 10
a = 1
while i:
if i % 2:
a = a * j
i /= 2
j *= j
return a
def power(n, i):
m = powm(i)
y = 1
x = 2
while n:
if n % 2 == 1:
y = y * x % m
x = x * x % m
n /= 2
return y
mylist = []
mylist.append(power(36, 2))
n = mylist[0]
print(n)
for i in range(3, 170):
p = power(n, i)
print p
if p != n:
mylist.append(p)
n = p
t = input()
while t:
x = raw_input().split(" ")
a = int(x[0])
b = int(x[1])
i = 0
#while i <= 150:
#print mylist[i]
#i += 1
#print power(8719476736,14)
while mylist[i] < a:
i += 1
ans = 0
while mylist[i] <= b:
i += 1
ans += 1
print ans
t -= 1
The final digits start to repeat after 20 increments. So for any n with the final digit 1, the final digit of the answer will be 2. So most values of n can be eliminated immediately.
2^1 = 2
2^21 = 2097152
2^101 = 2535301200456458802993406410752
2^2 = 4
2^22 = 4194304
2^42 = 4398046511104
In fact only two possibilities share a final digit:
2^14 = 16384
2^16 = 65536
2^34 = 17179869184
2^36 = 68719476736
If n is 14+20x or 16+20x, then it might work, so you'll need to check it. Otherwise, it cannot work.
I am not very good with such problems. But modular exponentiation appears to be key in your case.
Repeat for all n in the range A to B:
1. Find k, the no of digits in n. This can be done in O(logn)
2. Find 2^n (mod 10^k) using modular exponentiation and check if it is equal to n. This'll take O(n) time. (actually, O(n) multiplications)
EDIT
Actually, don't repeat the whole process for each n. Given 2^n (mod 10^k), we can find 2^(n+1) (mod 10^k) in constant time. Use this fact to speed it up further
EDIT - 2
This doesn't work for such large range.
This might be a no-brainer to some, but I'm trying to check if there are any duplicate values in my code.
To be clearer, I am creating 5 variable Integers that randomizes a number once they are created. Let's say they're named i1, i2, i3, i4, i5.
I want to run a loop to check on each other to make sure they don't have any possible duplicates. If they do, I'll re-random the second Integer that's being checked. (e.g if (i1 == i4) { i4.rand(); }) That's to make sure i1 doesn't need to get re-checked against all the previously checked values or being stuck in a long loop until a different number is found.
This is what I'm thinking if it was an entire if else statement : if (i1 == i2), if (i1 == i3), if (i1 == i4), if (i1 == i5), if (i2 == i3), if (i2 == i4), if (i2 == i5), if (i3 == i4), if (i3 == i5), if (i4 == i5)
I know I can probably do it "manually" by creating lots of if / else statements, but is there a better way to do it? It probably isn't very feasible if I increase my Integer limit to 20 and I have to if / else my way through 20 value checks. I know there is, but I just can't remember. Search on Google is turning up nothing (maybe I'm searching for the wrong keywords), which is why I'm asking over here at StackOverflow.
All I want to know is how do I do it, theory-wise (how would you check for duplicates in theory?). The answer doesn't necessarily need to be a workable function.
If you want to create a demo code using the programming language I'm using for this problem, itsExcel VBA. But I think this information would be able to apply theory-wise to a lot of other programming languages, so feel free to write in javascript/jQuery, C++, C#, etc. Just remember to comment!
You are looking for Set;
Set<Integer> hs = new HashSet<Integer>();
hs.add(i1);
if(!hs.add(i2)){
randomize(i2);
}
Hope this helps. Let me know, if you have any questions.
The above is just a concept of what to do.
To get the logic for your code, it will be
Set<Integer> hs = new HashSet<Integer>();
for(int count=0; count<Array.length; count++){ // Store the data into the array and loop
dataToInsert = Array[count];
while(hs.add(dataToInsert)){
dataToInsert = randomize(dataToInsert);
}
}
Here is a simple way to get your integers assuming you want to generate them in the range from 1 to N
Generate an integer from 1:N
Generate an integer from 1:N-1
Generate an integer from 1:N-2
Generate an integer from 1:N-(k-1)
Now interpret these as the position of the integer that you generated (in the set of total available integers for that number) and construct your real integer.
Example, N = 5, k=4
3
1
2
2
i1 = 3
i2 = 1
i3 = 4 (the available integers are 2 4 5)
i4 = 5
Note that this requires the minimum amount of random number generations.
To be clear, what you are attempting is the wrong approach. Theoretically, checking for duplicates and "re-randomizing" when one is found, could execute for an infinitely long time because existing integers could continuously be chosen.
What you should be doing is constructing the collection of integers in such a way that there will be no duplicates in the first place. Dennis Jaheruddin's answer does this. Alternatively, if you have a specific set of integers to choose from (like 1-20), and you simply want them in a random order, you should use a shuffling algorithm. In any event, you should start by searching for existing implementations of these in your language, since it has almost certainly been done before.
What you could do is loop over the List<int> and, for each element x at index i, loop while list.Take(i-1).Contains(x) and replace x with a new random number.
If you simply wanted a relatively inexpensive check that a given List<int> is full of unique numbers, however, you could do something like:
bool areAllUnique = list.Count() != list.Distinct().Count()`
2 ways I can think of.
1: Looping over all the values in your set and comparing each one to what you're adding.
2: Creating a simplistic version of a hash map:
var set
var map_size
create_set(n):
set <- array of size n of empty lists
map_size <- n
add_number(num_to_add):
if num_to_add not in set[num_to_add % map_size]:
add num_to_add to set[num_to_add % map_size]
return success
else:
return failure
populate_set():
loop 5 times:
i <- random_number()
while(add_number(i) == failure):
i <- random_number()
This way, each time you add a number, instead of checking against every other number in your set, you're only checking against at most [max value of integer] / [map size] values. And on average [number of elements in set] / [map size] (I think, correct me if I'm wrong) values.
Try
ArrayList<Integer> list = new ArrayList<Integer>();
while (list.size() < 5)
{
int i = Math.random() * max;
if (!list.contains(i))
{
list.add(i);
}
}
and you'll got in list 5 different Integers.
Pseudo-code:
Create an empty set S.
Generate a pseudo-random number r.
If r is in S, go to 2. Else, go to 4.
Add R to S.
If there are still variables to initialize, go to 2.
Exemplary implementation in Java:
public static void main(String[] args)
{
System.out.println(getUniqueRandoms(5, 10));
}
public static Set<Integer> getUniqueRandoms(int howMany, int max)
{
final Set<Integer> uniqueRandoms = new HashSet<Integer>(howMany);
while (uniqueRandoms.size() < howMany)
{
uniqueRandoms.add((int) (Math.random() * max));
}
return uniqueRandoms;
}
Output:
[8, 2, 5, 6, 7]
If you would like to have them in array, not in Set, just call toArray() on your Set.
In R is pretty simple...
i <- as.integer(runif(5, 1, 10))
for(l in seq_along(i)){
while(any(i[l]==i[-l])) # checks each against all the other
i[l] <- as.integer(runif(1, 1, 10))
}
However in R there is the function sample that picks random elements from a given vector without duplicates ( even though you can choose to have them)
> sample(1:10, 5)
[1] 2 5 1 9 6
> sample(1:10, 5)
[1] 3 5 8 2 1
> sample(1:10, 5)
[1] 8 3 5 9 4
> sample(1:10, 5)
[1] 1 8 9 10 5
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0; i < 5; i++)
{
int x;
do
{
x = random();
}
while(!set.Add(x));
}
int i1 = set.ElementAt(0),
i2 = set.ElementAt(1),
i3 = set.ElementAt(2),
i4 = set.ElementAt(3),
i5 = set.ElementAt(4);
This question is similar to this, but instead of an array that represents a square, I need to transpose a rectangular array.
So, given a width: x and a height: y, my array has x*y elements.
If width is 4 and height is 3, and I have:
{0,1,2,3,4,5,6,7,8,9,10,11}
which represents the matrix:
0 1 2 3
4 5 6 7
8 9 10 11
I would like:
{0,4,8,1,5,9,2,6,10,3,7,11}
I know how to do it by making a new array, but I'd like to know how to do it in place like the solution for the previously mentioned question.
A simple way to transpose in place is to rotate each element into place starting from the back of the matrix. You only need to rotate a single element into place at a time, so for the example, starting with [0,1,2,3,4,5,6,7,8,9,a,b], you get:
0,1,2,3,4,5,6,7,8,9,a,b, // step 0
,b, // step 1
,8,9,a,7, // step 2
4,5,6,8,9,a,3, // step 3
,a, // step 4
,8,9,6, // step 5
,4,5,8,9,2, // step 6
,9, // step 7
,8,5, // step 8
,4,8,1, // step 9
,8, // step 10
,4, // step 11
0, // step 12
(This just shows the elements rotated into their final position on each step.)
If you write out how many elements to rotate for each element (from back to front), it forms a nice progression. For the example (width= 4, height= 3):
1,4,7,1,3,5,1,2,3,1,1,1
Or, in a slightly better structured way:
1,4,7,
1,3,5,
1,2,3,
1,1,1
Rotations of 1 element are effectively no-ops, but the progression leads to a very simple algorithm (in C++):
void transpose(int *matrix, int width, int height)
{
int count= width*height;
for (int x= 0; x<width; ++x)
{
int count_adjustment= width - x - 1;
for (int y= 0, step= 1; y<height; ++y, step+= count_adjustment)
{
int last= count - (y+x*height);
int first= last - step;
std::rotate(matrix + first, matrix + first + 1, matrix + last);
}
}
}
One way to do this, is to move each existing element of the original matrix to its new position, taking care to pick up the value at the destination index first, so that it can also be moved to its new position. For an arbitrary NxM matrix, the destination index of an element at index X can be calculated as:
X_new = ((N*X) / (M*N)) + ((N*X) % (M*N))
where the "/" operator represents integer division (the quotient) and the "%" is the modulo operator (the remainder) -- I'm using Python syntax here.
The trouble is that you're not guaranteed to traverse all the elements in your matrix if you start at an arbitrary spot. The easiest way to work around this, is to maintain a bitmap of elements that have been moved to their correct positions.
Here's some Python code that achieves this:
M = 4
N = 3
MN = M*N
X = range(0,MN)
bitmap = (1<<0) + (1<<(MN-1))
i = 0
while bitmap != ( (1<<MN) - 1):
if (bitmap & (1<<i)):
i += 1
xin = X[i]
i = ((N*i)/MN) + ((N*i) % MN)
else:
xout = X[i]
X[i] = xin
bitmap += (1<<i)
i = ((N*i)/MN) + ((N*i) % MN)
xin = xout
print X
I've sacrificed some optimisation for clarity here. It is possible to use more complicated algorithms to avoid the bitmap -- have a look at the references in the related Wikipedia article if you're really serious about saving memory at the cost of computation.