program UniqueRandomSelection;
{$mode objfpc}{$H+}{$H-}
{
Goal:
- Select N random values that appear exactly once in the array.
- The array includes duplicates, but only values with frequency = 1
are eligible for selection.
Approach:
1. Count frequencies of each value.
2. Collect values that appear exactly once.
3. Shuffle the unique list.
4. Take the first N values.
5. Return them and print them.
Notes:
- Uses dynamic arrays for flexibility.
- Uses Randomize + Random for randomness.
- Uses clear, structured functions.
}
type
TIntArray = array of Integer;
{---------------------------------------------------------------}
function BuildFrequencyMap(const data: TIntArray): TIntArray;
var
freq: TIntArray;
i, j: Integer;
begin
SetLength(freq, Length(data));
{ Count how many times each value appears }
for i := 0 to High(data) do
begin
freq[i] := 0;
for j := 0 to High(data) do
if data[j] = data[i] then
Inc(freq[i]);
end;
Result := freq;
end;
{---------------------------------------------------------------}
function CollectGloballyUniqueValues(const data, freq: TIntArray): TIntArray;
var
unique: TIntArray;
count, i: Integer;
begin
{ Count how many values appear exactly once }
count := 0;
for i := 0 to High(data) do
if freq[i] = 1 then
Inc(count);
SetLength(unique, count);
{ Fill the unique array }
count := 0;
for i := 0 to High(data) do
if freq[i] = 1 then
begin
unique[count] := data[i];
Inc(count);
end;
Result := unique;
end;
{---------------------------------------------------------------}
function SelectRandomUnique(const unique: TIntArray; N: Integer): TIntArray;
var
temp: TIntArray;
resultArr: TIntArray;
i, j, swap, uniqueCount: Integer;
begin
uniqueCount := Length(unique);
if N > uniqueCount then
N := uniqueCount; { clamp }
{ Copy unique values into a temp array for shuffling }
SetLength(temp, uniqueCount);
for i := 0 to uniqueCount - 1 do
temp[i] := unique[i];
{ Fisher–Yates shuffle }
for i := uniqueCount - 1 downto 1 do
begin
j := Random(i + 1);
swap := temp[i];
temp[i] := temp[j];
temp[j] := swap;
end;
{ Take first N shuffled elements }
SetLength(resultArr, N);
for i := 0 to N - 1 do
resultArr[i] := temp[i];
Result := resultArr;
end;
{---------------------------------------------------------------}
procedure PrintArray(const arr: TIntArray);
var
i: Integer;
begin
for i := 0 to High(arr) do
Write(arr[i], ' ');
Writeln;
end;
{---------------------------------------------------------------}
var
data: TIntArray;
freq: TIntArray;
uniqueValues: TIntArray;
randomSelection: TIntArray;
N: Integer;
begin
Randomize;
{ Example array with duplicates }
data := TIntArray.Create(
5, 12, 5, 19, 5, 33, 19, 5, 8, 8, 8, 59, 61, 17, 3, 5, 3, 74, 83, 90, 3, 1
);
{ Step 1: Build frequency map }
freq := BuildFrequencyMap(data);
{ Step 2: Collect values that appear exactly once }
uniqueValues := CollectGloballyUniqueValues(data, freq);
{ Step 3: Choose how many unique random values to select }
N := 5;
{ Step 4: Select N random unique values }
randomSelection := SelectRandomUnique(uniqueValues, N);
{ Step 5: Print results }
Writeln('Values that appear exactly once:');
PrintArray(uniqueValues);
Writeln;
Writeln('Random selection (', N, ' values):');
PrintArray(randomSelection);
end.
{
run:
Values that appear exactly once:
12 33 59 61 17 74 83 90 1
Random selection (5 values):
33 59 90 83 74
}