I was curious to know if there is an efficient way to store data into a container that has a maximum amount of values and when that value is reached it start removing the oldest values in order to add new ones. And all this in an ordered fashion (meaning that new data should come after the last new data).
I know I could achieve this using a queue
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(3); // 1 2 3
q.Dequeue(); // 2 3
q.Enqueue(4); // 2 3 4
but in order to iterate through the data afterwards requires to transform the queue in an array, which I'm not sure how efficient it is.
Maybe it's better to have an array with a fixed size and have an index that shifts to the start when the array is full and using some modulo magic iterate always backwards to query the data from most recent to less recent. This would be less readable but working and more efficient I guess.
So my question would be, is there a better more readable and efficient way?
And also, what is the efficiency of using ToArray() when using other data structures (e.g. List, Queue, Stack..). When should this be avoided?
At the end I decided to implement my idea. Not sure if this is the best way, but it works well for my needs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataHolder<T> : IEnumerable
{
private T[] _data;
private int _maxSize;
private int _currIdx;
private int _currSize;
public DataHolder(int size)
{
_maxSize = size;
_data = new T[_maxSize];
_currIdx = -1;
_currSize = 0;
}
public void Add(T data)
{
if (_currSize < _maxSize) _currSize++;
_currIdx = NioUtils.PositiveMod((_currIdx + 1), _maxSize);
_data[_currIdx] = data;
}
///<summary>
/// Gets the element at index. The 0 element is the last one added.
///</summary>
public T GetElementAt(int index)
{
if (index >= _currSize)
{
throw new System.ArgumentException("Index out of bounds exception.", "index");
}
int shiftIndex = NioUtils.PositiveMod((_currIdx - index), _maxSize);
return _data[shiftIndex];
}
/// Implement interface IEnumerable in order to iterate throught this object.
public IEnumerator GetEnumerator()
{
int count = 0;
int index = _currIdx;
while (count < _currSize)
{
count++;
yield return _data[index];
index = NioUtils.PositiveMod((index - 1), _maxSize);
}
}
}
Where PositiveMod is:
public static int PositiveMod(int value, int n)
{
int v = value % n;
return v >= 0 ? v : n + v;
}
Related
For example, string "AAABBB" will have permutations:
"ABAABB",
"BBAABA",
"ABABAB",
etc
What's a good algorithm for generating the permutations? (And what's its time complexity?)
For a multiset, you can solve recursively by position (JavaScript code):
function f(multiset,counters,result){
if (counters.every(x => x === 0)){
console.log(result);
return;
}
for (var i=0; i<counters.length; i++){
if (counters[i] > 0){
_counters = counters.slice();
_counters[i]--;
f(multiset,_counters,result + multiset[i]);
}
}
}
f(['A','B'],[3,3],'');
This is not full answer, just an idea.
If your strings has fixed number of only two letters I'll go with binary tree and good recursion function.
Each node is object that contains name with prefix of parent name and suffix A or B furthermore it have numbers of A and B letters in the name.
Node constructor gets name of parent and number of A and B from parent so it needs only to add 1 to number of A or B and one letter to name.
It doesn't construct next node if there is more than three A (in case of A node) or B respectively, or their sum is equal to the length of starting string.
Now you can collect leafs of 2 trees (their names) and have all permutations that you need.
Scala or some functional language (with object-like features) would be perfect for implementing this algorithm. Hope this helps or just sparks some ideas.
Since you actually want to generate the permutations instead of just counting them, the best complexity you can hope for is O(size_of_output).
Here's a good solution in java that meets that bound and runs very quickly, while consuming negligible space. It first sorts the letters to find the lexographically smallest permutation, and then generates all permutations in lexographic order.
It's known as the Pandita algorithm: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
import java.util.Arrays;
import java.util.function.Consumer;
public class UniquePermutations
{
static void generateUniquePermutations(String s, Consumer<String> consumer)
{
char[] array = s.toCharArray();
Arrays.sort(array);
for (;;)
{
consumer.accept(String.valueOf(array));
int changePos=array.length-2;
while (changePos>=0 && array[changePos]>=array[changePos+1])
--changePos;
if (changePos<0)
break; //all done
int swapPos=changePos+1;
while(swapPos+1 < array.length && array[swapPos+1]>array[changePos])
++swapPos;
char t = array[changePos];
array[changePos] = array[swapPos];
array[swapPos] = t;
for (int i=changePos+1, j = array.length-1; i < j; ++i,--j)
{
t = array[i];
array[i] = array[j];
array[j] = t;
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
StringBuilder line = new StringBuilder();
generateUniquePermutations("banana", s->{
if (line.length() > 0)
{
if (line.length() + s.length() >= 75)
{
System.out.println(line.toString());
line.setLength(0);
}
else
line.append(" ");
}
line.append(s);
});
System.out.println(line);
}
}
Here is the output:
aaabnn aaanbn aaannb aabann aabnan aabnna aanabn aananb aanban aanbna
aannab aannba abaann abanan abanna abnaan abnana abnnaa anaabn anaanb
anaban anabna ananab ananba anbaan anbana anbnaa annaab annaba annbaa
baaann baanan baanna banaan banana bannaa bnaaan bnaana bnanaa bnnaaa
naaabn naaanb naaban naabna naanab naanba nabaan nabana nabnaa nanaab
nanaba nanbaa nbaaan nbaana nbanaa nbnaaa nnaaab nnaaba nnabaa nnbaaa
In the constructor of an Array is there a guarantee that the init function will be called for the indexes in an increasing order?
It would make sense but I did not find any such information in the docs:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/-init-.html#kotlin.Array%24%28kotlin.Int%2C+kotlin.Function1%28%28kotlin.Int%2C+kotlin.Array.T%29%29%29%2Finit
There is no guarantee for this in the API.
TLDR: If you need the sequential execution, because you have some state that changes see bottom.
First lets have a look at the implementations of the initializer:
Native: It is implemented in increasing order for Kotlin Native.
#InlineConstructor
public constructor(size: Int, init: (Int) -> Char): this(size) {
for (i in 0..size - 1) {
this[i] = init(i)
}
}
JVM: Decompiling the Kotlin byte code for
class test {
val intArray = IntArray(100) { it * 2 }
}
to Java in Android Studio yields:
public final class test {
#NotNull
private final int[] intArray;
#NotNull
public final int[] getIntArray() {
return this.intArray;
}
public test() {
int size$iv = 100;
int[] result$iv = new int[size$iv];
int i$iv = 0;
for(int var4 = result$iv.length; i$iv < var4; ++i$iv) {
int var6 = false;
int var11 = i$iv * 2;
result$iv[i$iv] = var11;
}
this.intArray = result$iv;
}
}
which supports the claim that it is initialized in ascending order.
Conclusion: It commonly is implemented to be executed in ascending order.
BUT: You can not rely on the execution order, as the implementation is not guaranteed by the API. It can change and it can be different for different platforms (although both is unlikely).
Solution: You can initialize the array manually in a loop, then you have control about the execution order.
The following example outlines a possible implementation that has a stable initialisation with random values, e.g. for tests.
val intArray = IntArray(100).also {
val random = Random(0)
for (index in it.indices) {
it[index] = index * random.nextInt()
}
}
Starting from the version 1.3.50 Kotlin has guaranteed sequential array initialization order in its API documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/-init-.html
The function init is called for each array element sequentially starting from the first one. It should return the value for an array element given its index.
I have some TableView with two columns - name and size;
This Table works with File objects;
PropertyValueFactory for columns can take properties of object, trying search somenameProrperty, getSomename, isSomename;
I'm need to get length() method from File.
columnName.setCellValueFactory(new PropertyValueFactory<>("name"));
columnSize.setCellValueFactory(new PropertyValueFactory<>("length"));
This code view file names (getName() method), but length colums is empty.
Know anyone what i can do with factory to get length() from File?
You should implement the cell value factory directly, instead of using the convenience (and somewhat legacy) class PropertyValueFactory.
Assuming your columnSize is a TableColumn<File, Number>, you can do
columnSize.setCellValueFactory(cellData ->
new SimpleLongProperty(cellData.getValue().length()));
If you want to format the data in the column more elegantly, you can additionally set a cell factory:
columnSize.setCellFactory(col -> new TableCell<File, Number>() {
#Override
protected void updateItem(Number length, boolean empty) {
super.updateItem(length, empty);
if (empty) {
setText(null);
} else {
setText(formatFileLength(length.longValue()));
}
}
});
// ...
private String formatFileLength(long length) {
final String[] unitNames = {"bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"};
int i ;
for (i = 0 ; length > 1024 && i < unitNames.length - 1 ; i++) {
length = length / 1024 ;
}
return String.format("%,d %s", length, unitNames[i]);
}
Found solution
columnSize.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<File, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<File, String> param) {
long size = param.getValue().length();
size = size/1024;
return new ReadOnlyObjectWrapper(String.valueOf(size));
}
});
I need to create a Map like data structure using an Array or ArrayLists.
Quick program over view: My map holds objects of Word which is a string and holds a frequency count of how many times the word appears in a next file.
Here is code for MyMap, Program outputs nothing.
List<Word>[] table;
int tableSize;
int index;
public MyMap(int tableSize){
table = new ArrayList[tableSize];
this.tableSize = tableSize;
}
//Problem!!
public void put(Word w){
index = Math.abs(w.hashCode()) % tableSize;
if(table[index].isEmpty()){
table[index].add(w);
}
else{
w.increaseFreq();
table[index].set(index, w);
}
}
public void displayMap(){
for(List<Word> w: table){
System.out.println(w);
}
}
}
How about using either a Generic.Dictionary<string,Word> or a KeyedCollection<string,Word>?
If you use the KeyedCollection then you will need to inherit from it and provide a GetKeyForItem implementation.
in this program i have used different array variable for each of
the fields in a
database.In database all fields having the same datatype and now i want to store all
the fields values into one array variable.is it possible???
import java.sql.*;
class ja1
{
public static void main(String ar[])
{
try
{
int x,i,j,k,l;
int a[]=new int[30];
int b[]=new int[30];
int c[]=new int[30];
int d[]=new int[30];
int count[]=new int[10];
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection c1=DriverManager.getConnection("Jdbc:Odbc:ds");
Statement s=c1.createStatement();
ResultSet r=s.executeQuery("select * from pro");
i=0;
j=0;
k=0;
l=0;
x=0;
while(r.next())
{
a[i]=r.getInt(2);
i++;
b[j]=r.getInt(3);
j++;
c[k]=r.getInt(4);
k++;
d[l]=r.getInt(5);
l++;
}
for(i=0;i<6;i++)
System.out.println(""+a[i]);
for(j=0;j<6;j++)
System.out.println(""+b[j]);
System.out.print("\n\n");
for(k=0;k<6;k++)
System.out.println(""+c[k]);
System.out.print("\n\n");
for(l=0;l<6;l++)
System.out.println(""+d[l]);
}
catch(Exception e)
{
System.out.print(e);
}
}
}
Yes, it is possible in several ways :
1) If you want to use only one array then please create an array with size of 120 (4X30) and use 4 counter to arrange your data in range. That means, your first variable would be from index 0 to 29, the 2nd would be from 30 to 69 and so on. This is not good if you don't know the exact size of your array as you are binding them with perfect size of 30.
2) You can create a POJO and have 4 arrays into it, you can use a List instead of array, but it depends on your implementation. So, create a class, put 4 arrays into it, give good variable names and access thru getter/setter methods. This will be a clear code
3) You can use a Map<Integer,Integer[]> or Map<Integer,List<Integer>> and have a single variable/reference which is holding your key value pair.
It all depends on you, if you dont know, why are you using arrays,then please move the Collection
I would define a POJO for the record and then use a generic list to add and iterate the record/s
Try this:
class RecordData
{
public int First;
public int Second;
public int Third;
public int Fourth;
}
class ja1
{
public static void main(String ar[])
{
try
{
List<RecordData> list = new ArrayList<RecordData>;
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection c1=DriverManager.getConnection("Jdbc:Odbc:ds");
Statement s=c1.createStatement();
ResultSet r=s.executeQuery("select * from pro");
while(r.next())
{
RecordData data = new RecordData();
data.First = r.getInt(2);
data.Second = r.getInt(3);
data.Third = r.getInt(4);
data.Fourth = r.getInt(5);
list.add(data);
}
for(RecordData data : list) {
System.out.println(data.First);
System.out.println(data.Second);
System.out.println(data.Third);
System.out.println(data.Fourth);
}
}
catch(Exception e)
{
System.out.print(e);
}
}
}