what I want to do is check an array of bools to see if 3 or more of them have been set to true. The only way I can think to do this is using a if statement for each possible combination of which there is lots because there are ten bools. Dose anybody have any suggestions on how best to do this.
This would be the easiest way:
std::count(bool_array, std::end(bool_array), true) >= 3
Only problem is it keeps counting even after it has found 3. If that is a problem, then I would use sharptooth's method.
side note
I've decided to fashion an algorithm in the style of std::all_of/any_of/none_of for my personal library, perhaps you will find it useful:
template<typename InIt, typename P>
bool n_or_more_of(InIt first, InIt last, P p, unsigned n)
{
while (n && first != last)
{
if (p(*first)) --n;
++first;
}
return n == 0;
}
For your purpose, you would use it like this:
n_or_more_of(bool_array, std::end(bool_array), [](bool b) { return b; }, 3);
The much easier way would be to loop through the array:
int numberOfSet = 0;
for( int i = 0; i < sizeOfArray; i++ ) {
if( array[i] ) {
numberOfSet++;
//early cut-off so that you don't loop further without need
// whether you need it depends on how typical it is to have
// long arrays that have three or more elements set in the beginning
if( numberOfSet >= 3 ) {
break;
}
}
}
bool result = numberOfSet >= 3;
Whenever you are setting an array element into TRUE value, you can increment a global counter. This will be the simplest way. At any point in your code, the global array will tell you the number of TRUE elements in the Array.
Another thing - if you are keeping upto 32 bool values, you can use a single int variable. int is 32 bits (in Win32) and you can store 32 bool.
char x = 0; // 00000000 // char is 8 bits
// TO SET TRUE
x = x | (1 << 4); // 00010000
x = x | (1 << 7); // 10010000
// TO SET FALSE
x = x & ~(1 << 4); // 10010000 & 11101111 => 10000000
// TO CHECK True/False
if( x & ~(1 << 4) )
If it's an array, what you do is loop over it and count the number of trues. But I'm afraid you mean a bitpattern of some kind, right?
Why not just count the number of trues and then do something if the number is 3 or higher:
int sum = 0;
for (int i = 0; i < length; i++){
if (arr[i]){
sum++;
}
}
if (sum >= 3){
// do something...
}
You can loop through and build a bit-mask representation of the array, then you can compare against up to CHAR_BIT * sizeof (unsigned long) in parallel:
unsigned long mask = 0;
for (std::vector<bool>::const_iterator it = flags.begin(), end_it = flags.end();
it != end_it;
++it)
{
if (*it)
mask |= (1 << (it - flags.begin()));
}
if (mask & (0xaa3)) // or whatever mask you want to check
{
}
This assumes that you're looking for patterns, not just want to count the number of true flags in the array.
Just loop through the array counting the number of bools set to true.
/**
* #param arr The array of booleans to check.
* #param n How many must be true for this function to return true.
* #param len The length of arr.
*/
bool hasNTrue(bool *arr, int n, int len) {
int boolCounter;
for(int i=0; i<len; i++) {
if (arr[i]) boolCounter++;
}
return boolCounter>=n;
}
Then call it like so
hasNTrue(myArray, 3, myArrayLength);
Store the bools as bits in an integer. Then apply one of the bit twiddling hacks.
Related
I was practicing on Leetcode and came across this problem.
Problem statement (link):
You are given an array nums consisting of non-negative integers.
You are also given a queries array, where queries[i] = [xi, mi].
The answer to the ith query is the maximum bitwise XOR value of xi and any element of nums that does not exceed mi.
In other words, the answer is max(nums[j] XOR xi) for all j such that nums[j] <= mi.
If all elements in nums are larger than mi, then the answer is -1.
Return an integer array answer where answer.length == queries.length and answer[i] is the answer to the ith query.
Constraints:
1 <= nums.length, queries.length <= 10^5
queries[i].length == 2
0 <= nums[j], xi, mi <= 10^9
I solved this question using the trie approach and went to discuss section to see other's solutions. There, I came across this solution (link):
class Solution {
public:
vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) {
const int n = nums.size(), q = queries.size();
vector<int> ans(q, -1);
sort(nums.begin(), nums.end());
for (int i = 0; i < q; i++) {
const int x = queries[i][0], m = queries[i][1];
if (m < nums[0]) continue;
int end = upper_bound(nums.begin(), nums.end(), m) - nums.begin();
int start = 0;
int k = 0, cur = 0;
for (int bit = 31; bit >= 0; bit--) {
if (x & (1 << bit)) { // hope A[i] this bit == 0
if (!(nums[start] & (1 << bit))) {
k |= 1 << bit;
end = lower_bound(nums.begin() + start, nums.begin() + end, cur | (1 << bit)) - nums.begin();
} else {
cur |= 1 << bit;
}
} else { // hope: A[i] this bit == 1
if (start <= end - 1 && (nums[end - 1] & (1 << bit))) {
k |= 1 << bit;
cur |= 1 << bit;
start = lower_bound(nums.begin() + start, nums.begin() + end, cur) - nums.begin();
}
}
}
ans[i] = k;
}
return ans;
}
};
Unfortunately, I'm not able to understand this solution. I would appreciate it if someone can give a proper explanation for this solution (mainly while looping through bits).
There are some issues with this implementation. start and end should remain iterators, they could be used directly without adding/subtracting nums.begin() all the time. We're talking about non-negative integers, so provided they fit into normal int first bit is 0 anyway, so we should start with int bit = 30 to skip one needless iteration. For integers right as for iterators as well, start <= end - 1 is better compared as start < end. The code consists of one single function, there's absolutely no need for a class then, so one should prefer a namespace. Applying these changes, the code would look like this:
namespace Solution
{
// as EXACTLY two values, std::pair is more appropriate
// we are not modifying queries, so should be accepted as const
std::vector<int> maximizeXor
(
std::vector<int>& nums, std::vector<std::pair<int, int>>const& queries
)
{
const int q = queries.size();
std::vector<int> ans(q, -1);
sort(nums.begin(), nums.end());
// remove duplicates:
// -> less numbers to iterate over
nums.erase(unique(nums.begin(), nums.end()), nums.end());
for (int i = 0; i < q; ++i)
{
int const x = queries[i].first, m = queries[i].second;
// we have a sorted array, remember?
// if first value is larger than the query maximum, then there are no
// corresponding numbers – and as the vector is initialised to -1
// anyway, the appropriate value is there already so we can simply skip
if (m < nums[0])
{
continue;
}
// using iterators pointing at the appropriate indices
auto end = upper_bound(nums.begin(), nums.end(), m);
auto start = nums.begin();
int /*k = 0,*/ cur = 0;
// intention is to check each bit of x
// modifying the loop!
//for (int bit = 30; bit >= 0; bit--)
int const MaxBit = 1 << sizeof(int) * CHAR_BIT - 2;
for (int bit = MaxBit; start != prev(end); bit >>= 1)
{
// OK; fixing an issue and adding some tricks to handle the loop
// a bit cleverer...
// sizeof(int) * CHAR_BIT: int is NOT guaranteed to have exactly
// 32 bits! if you want to be on the safe side, either calculate
// as above or use int32_t instead
// changed abort condition:
// I modified the algorithm slightly such that we can break early
// unique'ing the vector allows us to drop the original
// condition bit >= 0 entirely, this will be explained later
// I store the bit-MASK in bit now, now we do not have to
// calculate it again and again (1 << bit)
if (x & bit)
{
// so x has a 1-bit at bit index 'bit'
// in the range yet to be considered we have two groups of
// numbers:
// 1. those having a 0-bit at bit-index 'bit'
// 2. those having a 1-bit
// if we compare single bits, we get:
// x = *1***
// num = *0*** XOR: *1***
// num = *1*** XOR: *0***
// IF now there are numbers with a zero bit at all, then one
// of these will produce the maximum, whereas those with a
// 1-bit cannot asnumbers are sorted, we can just check very
// first value of the range:
// any number having a 1-bit at the same bit index will produce
// a zero-bit – thus these numbers CANNOT produce the maximum
if (!(*start & bit))
{
// bits differ, remember?
// thus the XOR will have a one-bit we store right now
// actually, we do NOT need that, we can handle that cleverer
//k |= 1 << bit;
// instead, I handle this with the NEW loop condition
// fine – there ARE numbers with zero-bits, so remove all
// numbers with 1-bit from range; as they all are at the end
// of, we simply move this one towards front:
end = lower_bound(start, end, cur | bit);
// cur contains those bits of the number producing the
// maximum that have been evaluated so far, it is a
// lower bound for – we do NOT modify it, but we can
// calculate a new upper bound from!
}
else
{
// well, there is no such number with a 0-bit
// we cannot move end or start position
cur |= bit;
}
}
else
{
// analogously:
// x = *0***
// num = *0*** XOR: *0***
// num = *1*** XOR: *1***
// so all members having a 1-bit are of interest – IF there
// are – and we can skip those numbers with 0-bit at the
// beginning
// if there are, then they are at the very end
// 'end' iterator points to one past, so we need predecessor
if (/*start < end &&*/ *prev(end) & bit)
{
// first condition is handled in the loop now
// as above: we can handle that cleverer
//k |= 1 << bit;
// now current mask NEEDS the one-bit
cur |= bit;
start = lower_bound(start, end, cur);
}
}
// with unchanged loop it was not possible to break early as k still
// needed to be calculated
//ans[i] = k;
// with or without early break, we can always:
ans[i] = *start ^ x;
// with every iteration, we extend the bit mask 'cur' the numbers
// have to match with by one bit (either the 0 gets confirmed
// or replaced by a 1).
// After 31 iterations (sign bit is ignored as we only have
// positive integers), *all* bits are defined (if we had omitted
// the early breaks we could have calculated
// ans[i] = cur ^ x; as well...).
// so all numbers that yet might have remained in the valid range
// must match this pattern, i. e. be equal. However as unique-ing,
// there is exactly one single value left...
}
}
return ans;
}
} // namespace Solution
Be aware that std::lower_bound has (random access iterators provided, as is with std::vector) a complexity of O(log(n)), so executing one single query has O(log(n)) with n being the amount of numbers. Adding the overhead of sorting and querying m times, we get a total complexity of O(n*log(n) + m*log(n)) = O((n+m)*log(n)) compared to 'naive' iteration with complexity of O(m*n). If m is of similar magnitude as n or larger we have a complexity advantage (already in original variant, my adjustments just trim the constants a bit, but do not change complexity).
Disclaimer: This question is more of a challenge, and the post is also quite long. Read only in free time!
The Problem:
Basically, suppose there is a single line of integer inputs:
32352\n // assuming single digits only and no spaces for simplification
We have to remove duplicates from the inputs, and then display them. So, output should be:
After removing duplicates: 2, 3, 5 // display them in any order
However, there is a catch:
Do not use any data structures containers.
Edit: I believe containers are what I meant (thanks Vlad!).
So, my question is: What is the error in my implementation, and is there another (better) way to do it?
My thought process:
Since we are not allowed use of any data structure, we cannot store the inputs (I think?).
However, since it is already stored in memory on input, that is not a problem.
More of a problem is removing the duplicates. We will have to manipulate the input stream.
The first thing that struck me is that we can sort the inputs. That is,
32352
becomes:
22335
And now, simply print the first element of each range.
Working on this idea, I came across the std::cin.get() and std::cin.putback() methods, both accepting a char.
I also realized I would have to use recursion.
And hence, the code becomes (I have used insertion sort):
The Code:
The sort() function is where the error is. It uses a running index ala arrays, and this is used to uniquely identify each element.
In each iteration, the index_of_element element is found and selected, and we determine where in the remaining (virtual) array, we need to place it. For example, if in our original input:
32352 // S = sorted subarray
SU--U // U = unsorted subarray
, the first 2 is selected, we "shift" 3 (as 3 < 2).
Now, there are no more elements left to shift, we "place" 2.
The result should become:
23352
SSU-U
The (buggy) implementation:
bool sort(int index_of_element, int index = 0, char prev_element = 0)
{
static char element;
char digit;
// retrieve an element from memory
std::cin.get(digit);
// If not end of input
if(digit != '\n')
{
// store the element for comparision
if(index == index_of_element)
{
element = digit;
}
// continue forward until '\n'
bool result = sort(index_of_element, index + 1, digit);
// if we are in sorted subarray
if(index <= index_of_element)
{
// If element belongs here(also if this is first element(prev_element is 0)), place it
if(element > prev_element)
{
digit = element;
// Signal that element has been placed
element = 0;
}
// Else, if element not already placed, we need to shift elements
else if(element != 0)
{
// Place the previous element here
digit = prev_element;
}
}
// Put it back in memory
std::cin.putback(digit);
// And return the result
return result;
}
// Which is generated here when end of input is reached
else
{
// If sorted all elements, break loop
if(index_of_element == index)
{
return false;
}
// Else, continue sorting
else
{
return true;
}
}
}
(A wall of code, but I didn't want to skip anything relevant), and it should be used as:
...
int index_of_element = 0;
while(sort(index_of_element++));
...
The display function is ready, and it works properly.
What I do know is that it gets stuck in an infinite loop and the values are lost.
What is going wrong?
And should I add the output (The post is already very long)?
The problem seems to be that you don't put the newline back into the stream, while your code assumes that it will be there.
That is, after your first pass, digit != '\n' is always true.
Put the newline back into the stream, or break when you've reached the true end-of-stream.
(There could also be problems with (ab)using std::cin like this, but I'm not sure, and that's another matter anyway.)
You can do it with only function objects, in a single pass.
#include <iostream>
#include <sstream>
#include <functional>
void print_unique_ints(std::istream & in, std::ostream & out, std::function<bool(int)> unseen) {
for (int i; in >> i;) {
if (unseen(i)) {
out << i << ' ';
print_unique_ints(in, out, [&](int j){ return (i != j) && unseen(j); });
return; // not actually needed, previous call only ends when input is exhausted
}
}
}
int main() {
print_unique_ints(std::cin, std::cout, [](int){ return true; });
}
See it live
Each call to print_unique_ints skips previously seen ints, prints the unseen int, and adds to the filter
Substituting values for variables; and function calls for expressions; in the first call
for (int i; in >> i;) { // i = 3
if (true) {
out << 3 << ' ';
print_unique_ints(...) // see below
}
}
The second
for (int i; in >> i;) { // i = 2
if ((3 != i) && true) {
out << 2 << ' ';
print_unique_ints(...) // see below
}
}
The third
for (int i; in >> i;) { // i = 3, 5
if ((2 != i) && (3 != i) && true) { // skips over the 3
out << 5 << ' ';
print_unique_ints(...) // see below
}
}
The forth
for (int i; in >> i;) { // i = 2
if ((5 != i) && (2 != i) && (3 != i) && true) { // skips the 2 and finds the end of input
}
}
Note that && true never changes the result in the if
A variation of bitset (or mask) implem...using the commutative property of multiplication
Take a function f which maps every digit to a unique prime p_i
0 1 2 3 4 5 6 7 8 9
2,3,5,7,9,11,13,17,19,23
If all numbers are found the total amount to N=2*3*5*7*9*11*13*17*19*23=2007835830
Consume cin as c, if f(c) divides N, print c and update N /= f(c)
#include <iostream>
#include <sstream>
int f(char c){
if(c=='0') return 2;
if(c=='1') return 3;
if(c=='2') return 5;
if(c=='3') return 7;
if(c=='4') return 9;
if(c=='5') return 11;
if(c=='6') return 13;
if(c=='7') return 17;
if(c=='8') return 19;
if(c=='9') return 23;
}
int main() {
std::istringstream in("2 2 2 3 5");
int N = 2007835830;
char c;
while(in >> c){
if(c=='\n') break;
int p_i = f(c);
if(N % p_i == 0){
N = N/p_i;
std::cout<<c<<" ";
}
}
}
I am sure that this phrase
Remove duplicates from input without use of any data structures
means that you shall not use any container like for example std::string or an ordinary array.
The assignment is not simple for a beginner.
Here are my five cents.
#include <iostream>
#include <type_traits>
template <typename T>
T remove_duplicates( T n )
{
static_assert ( std::is_integral<T>::value );
const T Base = 10;
T result = n % Base;
for ( T multiplier = 1; n /= Base; )
{
T digit = n % Base;
T tmp = result;
bool unique = true;
while ( ( unique = tmp % Base != digit ) && ( tmp /= Base ) );
if ( unique )
{
multiplier *= Base;
result = digit == 0 ? result * multiplier + digit
: digit * multiplier + result;
}
}
return result;
}
int main()
{
for ( int n : { 0, 1, 10, 101, 100, 10203, -1, -10, -101, -100, - 10203 } )
{
std::cout << n << ": " << remove_duplicates( n ) << '\n';
}
return 0;
}
The program output is
0: 0
1: 1
10: 10
101: 10
100: 10
10203: 1230
-1: -1
-10: -10
-101: -10
-100: -10
-10203: -1230
That is you are building a new number from the source number by checking whether the new number already contains a digit from the source number.
The function can work with any integer type signed or unsigned. It correctly processes digits equal to 0.
It was said not to use any arrays, vectors, stacks, queues etc and neither our own implementations of it. I simplified the condition.
Well I've got bad news for you; this is not possible.
Given an input of length N you will need to somehow remember the previous N - 1 values to decide whether to print the Nth value or not. This is not possible with constant space.
So you need some data structure.
Now ...
Since we are not allowed use of any data structure, we cannot store the inputs (I think?).
However, since it is already stored in memory on input, that is not a problem.
So let's assume the existence of a (mutable) array of length N, containing the input values. Now we can solve this without using additional storage / data structures:
Select some value as special value
Iterate over the numbers until you find a value which is not that special value. print that value. Write the special value to the array where you found the value you just printed. finish iterating over the numbers, overwritte each occurrence of the just printed value with the special value.
repeat (from 2) until the input consists only of special values.
You just need to think about a way to handle the case where the special value was present in the input from the start.
I wrote some C++ code to solve this problem:
#include <iostream>
#include <cmath>
using namespace std;
unsigned int countSetBits(unsigned int n)
{
int totalCount = 0, i;
int cond = n-1;
for(i=0;i<pow(2,n);i++){
unsigned int count = 0;
while (i) {
count += i & 1;
i >>= 1;
}
if(count == cond){
totalCount++;
}
}
return totalCount;
}
int main()
{
int n=5;
cout<<countSetBits(5);
return 0;
}
Although it is compiling succesfully, it doesn't print anything.
I can't figure out where is the problem...
Pen and paper solution:
N=2 2^N-1 = 0b11 Possible integers with 1 bit set:
01
10
N=3 2^N-1 = 0b111 Possible integers with 2 bits set:
011
101
110
N=4 2^N-1 = 0b1111 Possible integers with 3 bits set:
0111
1011
1101
1110
So, N seems to be the answer.
The problem is that you are modifying the 'control' variable (i) of your for loop inside that loop, so that the value of i will never reach the loop limit and it will run forever.
To fix this, take a copy of the current i value and modify that:
unsigned int countSetBits(unsigned int n)
{
int totalCount = 0, i;
int cond = n - 1;
int limit = pow(2, n); /// Calculate this ONCE, rather than on each loop!
for (i = 0; i < limit; i++) {
unsigned int count = 0;
int j = i; /// Take a copy of i here (otherwise it will keep getting reset to zero)...
while (j) { /// ...and do your test on the copy!
count += j & 1;
j >>= 1;
}
if (count == cond) {
totalCount++;
}
}
return totalCount;
}
There are also other improvements you can make, as mentioned in the comments. But the code changes I have posted at least fix your problem.
You modify i inside the loop. The inner while loop will always make i == 0, no matter what the loop counter is, hence the condition for the for loop will never be false. Use a temporary. Also don't use pow to calculate powers of 2. 2^N is (1 << N).
You need N+1 bits to represent 2^N. (2^N)-1 has the N lower bits set. There are N possible bits to unset in (2^N)-1, hence there are N numbers with N-1 bits set in [0,2^N). qed ;)
unsigned int countSetBits(unsigned int n) { return n; }
The remove_dup function has a run-time complexity of O(n^2) since there are two nested repetitive loops inside. My task is to get the same results with O(n).
I don't really have a clue how that could look like.
int add_without_dup (char x, vector<char>& r)
{// pre-condition:
assert (true) ;
// post-condition: x is added to the end of r if it is not yet present in r
// the result is the number of comparisons performed in this function
int i = 0 ;
while ( i < size(r) && r[i] != x )
i++ ;
if ( i == size(r))
r.push_back (x) ;
return i ;
}
int remove_dup (vector<char>& source, vector<char>& dest)
{// pre-condition:
assert (size (dest) == 0) ;
// post-condition: dest is a copy of source without duplicate elements
// the result is the number of comparisons performed in this function
int nr_of_comparisons = 0 ;
for (int i = 0 ; i < size (source) ; i++)
nr_of_comparisons += add_without_dup (source[i], dest) ;
return nr_of_comparisons ;
}
Because your char can only have 256 possible values, you can keep an bool array[256]. When you insert something in you set the value to true. When you want to check if it is in you check if the value is set to true or not.
The complexity is O(N + S) where S is the number of possible values you want to have in your vector.Usually, for char, N >> S, so S will not matter.
Use a single-subscripted array to solve the following problem: Read in 20 numbers, each of which is between 10 and 100, inclusive. As each number is read, print it only if it is not a duplicate of a number already read. Provide for the "worst case" in which all 20 numbers are different. Use the smallest possible array to solve this problem.
here is what I have so far:
#include <stdio.h>
#define SIZE 20
int duplicate (int num[] );
int main ()
{
int i, numbers[ SIZE ];
printf( " Enter 20 numbers between 10 and 100:\n " );
scanf_s( "%d\n" );
for (int i = 0; i < SIZE - 1; i++ );
{
int duplicate( int num[] )
{
int i, hold;
for ( i = 0; i <= SIZE - 1; i++ )
if ( num[i] == num[i=1] ){
hold = num[i];
else
hold = num[i+1];
}
printf( "%3d\n," num[ i ] );
}
Your professor is, unfortunately, probably not smart enough to solve his own problem. The smallest possible array for this problem is size 2 (Assuming a 64-bit data type, which is the largest the standard provides for. With 32-bit integers it would need three elements, and with 128-bit integers, just 1).
#include <stdint.h>
#include <stdio.h>
int main(void)
{
int_fast64_t visited[2] = { 0 };
int inputs_left = 20;
do {
int input, slot;
int_fast64_t mask;
puts("Enter an integer between 10 and 100: ");
if (!scanf("%d", &input)) {
puts("That's not a number!\n");
continue;
}
if (input < 10 || input > 100) {
puts("Out of range!\n");
continue;
}
slot = (input - 10) >> 6;
mask = 1 << ((input - 10) & 0x3F);
if (visited[slot] & mask) {
puts("Already seen, it is a duplicate.\n");
}
else {
visited[slot] |= mask;
printf("%d is new\n", input);
}
inputs_left--;
} while (inputs_left);
return 0;
}
You are welcome to use this code in your assignment, if you are able to correctly explain how it works (I hope your professor taught you how to write comments).
This is what I came up with, thanks for everybody's help:
#include <stdio.h>
#define MAX 20
int main()
{
int a[ MAX ] = { 0 }; /* user input */
int i; /* counter */
int j; /* counter */
int k = 0; /* number of integers entered */
int duplicate; /* notify of duplicates */
int value;
printf( "Enter 20 numbers between 10 - 100;\n" );
/* ask user for 20 numbers */
for ( i = 0; i <= MAX - 1; i++ ){
duplicate = 0;
scanf( "%d", &value);
/* decide if integer is duplicate */
for ( j = 0; j < k; j++ ) {
/* notify and stop loop if duplicate */
if ( value == a[ j ] ) {
duplicate = 1;
break;
{ /* end if */
/* enter number into array if it's not a duplicate */
if ( !duplicate )
a[ k++ ] = value;
} /* end if */
There are a few problems with your code:
The duplicate function is inside the main function.
i is declared multiple times
There should not be a semicolon after your first for loop.
The hold variable is not being used for anything. It is only being assigned a value.
num[i=1] - not sure what you are trying to do here, but the i=1 is setting i to 1.
In your first for loop, your condition is i < SIZE - 1, meaning it will loop 19 times, not 20. It should be i < SIZE or i <= SIZE - 1.
Your if statements should use braces ({}) for each if/else, or not at all.
if (test) {
// code
}
else {
// code
}
or
if (test)
// code
else
// code
As for the logic:
You are only getting one integer, which you are not putting in the numbers array. You will need to get 20 integers one by one and check the array each time the user enters a number.
The duplicate function should probably take a second parameter, the number that you want to check for. The if statement would check if num[i] equals the number you are looking for.
Remember to initialize the array values and only check values that you have set. For example, when the user enters the third number, you only want to check the first 2 numbers in the array to see if it already exists.
PS: Please try to indent your code properly. Many people will not even try to help if it is not indented properly.
My C is pretty rusty, so here's a pseudo-code solution (since this is homework you should do some of it for yourself):
print initial prompt;
declare nums[ array size 20 ]; // I later assume a 0-based index
declare boolean found;
for (i=0; i < 20; i++) {
// prompt for next number if desired
read next number into nums[i];
found = false;
// compare against all previously read numbers
for (j=0; j < i; j++) {
if (nums[j] == nums[i]) {
found = true;
break;
}
}
if (!found) {
print nums[i];
}
}
Note: the question as stated doesn't say the numbers have to be integers. Also, it says "use the smallest possible array" - you could do it with a 19 element array if you introduce a non-array variable for the current number (since the 20th number read only needs to be checked against the previous 19, not against itself), but that makes the code more complicated.
See also the comment I posted above that mentions some specific things wrong with your code. And check that all of your brackets match up.