Generate Random no between x and y whose sum is m - android

I want to generate n no of random no whose sum should be m and these no should always be between x and y.
For eg :- If i say I need 20 no, between 3 and 9 inclusive, whose sum should be 100.
I want to specify the sum and required amount of no as well as the limit between which random no should be generated and it should give me the random no of specified amount. Below is my code which do generates no which are greater than 2 but i am not able to put the max limit. Also, the sum which comes out and the sum of no. which it generates is not equal to specified sum. I am totally confused Please help me out.
TextView textView,randomTotaltxt;
int count0 = 0;
int count1 = 0;
int targetSum = 100;
int numberofDraws = 20;
textView = (TextView) findViewById(R.id.textview);
randomTotaltxt = (TextView) findViewById(R.id.randomTptalText);
Random r = new Random();
ArrayList<Integer> load = new ArrayList<>();
//random no
int sum = 0;
for (int i=0; i<numberofDraws;i++){
int next = r.nextInt(targetSum)+1;
Log.d("No",""+next);
load.add(next);
sum += next;
}
//scale it
double scale = 1d*targetSum/sum;
sum=0;
for (int i=0; i<numberofDraws;i++){
load.set(i, (int)(load.get(i)*scale));
sum += load.get(i);
}
while (load.contains(0)|| load.contains(1)){
for (int i=0; i<load.size();i++) {
if (load.get(i).equals(0)) {
load.set(i, load.get(i) + 2);
count0++;
sum = sum+1;
}
if (load.get(i).equals(1)) {
load.set(i, load.get(i) + 2);
sum += load.get(i);
count1++;
sum = sum+1;
}
}
}
// take rounding
while (sum++ <targetSum){
int i = r.nextInt(numberofDraws);
load.set(i, load.get(i) + 1);
}
textView.setText(""+load);
randomTotaltxt.setText(""+(sum-1));

This might not be the optimal solution but this will do your work as required.
int targetSum = 100;
int numberOfDraws = 20;
int uppr=0;
int countt =0;
ArrayList<Integer> load = new ArrayList<>();
Random random;
TextView textView1,randomTotaltxt1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
textView1 = (TextView) findViewById(R.id.textview1);
randomTotaltxt1 = (TextView) findViewById(R.id.randomTptalText1);
random = new Random();
//random no
int sum = 0;
for (int i=0; i<numberOfDraws;i++){
int next = random.nextInt(targetSum)+1;
load.add(next);
sum += next;
}
//scale it
double scale = 1d*targetSum/sum;
sum=0;
for (int i=0; i<numberOfDraws;i++){
load.set(i, (int)(load.get(i)*scale));
sum += load.get(i);
}
// take rounding
while (sum++ <targetSum){
int i = random.nextInt(numberOfDraws);
load.set(i, load.get(i) + 1);
Log.d("TAG",""+load);
}
checkForUpperRange();
}
public void checkForUpperRange(){
for (int i=0; i<numberOfDraws;i++){
int n = load.get(i);
if (n > 9){
load.set(i, 9);
uppr = n - 9; // getting the required no.
adjustUpper();
break;
}
checkForLowerRange();
}
}
private void adjustUpper() {
for (int j=0; j<numberOfDraws;j++){
if (load.get(j) > 2){
load.set(j, load.get(j)+uppr); // uppr is added
checkForUpperRange();
break;
}
}
}
public void checkForLowerRange(){
for (int i=0; i<numberOfDraws;i++){
int n = load.get(i);
if (n == 0){
load.set(i, load.get(i)+3); // 3 is added in sum
adjust0();
break;
}
if (n == 1){
load.set(i, load.get(i)+2); // 2 is added in sum
adjust1();
break;
}
if (n == 2){
load.set(i, load.get(i)+1); // 1 is added in sum
adjust2();
break;
}
getCount();
}
}
public void getCount(){
countt = 0;
for (int k=0; k<numberOfDraws;k++){
countt = countt+ load.get(k);
showResult();
}
}
public void showResult(){
textView1.setText(""+load);
randomTotaltxt1.setText(""+countt);
}
public void adjust0(){
for (int j=0; j<numberOfDraws;j++){
if (load.get(j) > 3){
load.set(j, load.get(j)-3); // 3 is subtracted
checkForLowerRange();
break;
}
}
}
public void adjust1(){
for (int j=0; j<numberOfDraws;j++){
if (load.get(j) > 3){
load.set(j, load.get(j)-2); // 2 is subtracted
checkForLowerRange();
break;
}
}
}
public void adjust2(){
for (int j=0; j<numberOfDraws;j++){
if (load.get(j) > 3){
load.set(j, load.get(j)-1); // 1 is subtracted
checkForLowerRange();
break;
}
}
}

Related

Android: How to generate unique random numbers in an array and perform bubble sort?

The following is my code but it doesn't generate unique random numbers
Random rand = new Random();
int[] array = new int[n];
for (int i = 0; i < n; i++){
array[i] = rand.nextInt(n)+1;
}
for (int i = 0; i < ( n - 1 ); i++)
{
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
public TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.textView);
Random r = new Random();
StringBuffer temp =new StringBuffer("Random numbers:");
for(int i=0;i<10;i++) {
int i1 = r.nextInt(100 - 0) + 0;
temp.append(String.valueOf(i1));
temp.append(String.valueOf(" "));
}
tv.setText(temp.toString());
}
//here ,,I generate 10 random numbers and save it in to stringBuffer and dispaly it in to textView..here range is up to 0 to 100...you can take your own Range ...I hope ,,It will help you...
check this out!... it works for me
Random rand = new Random();
int n = 10;
int[] array = new int[n];
for (int i = 0; i < n; i++){
array[i] = (int) (rand.nextDouble() * n + 1);
}
for (int i = 0; i < ( n - 1 ); i++)
{
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
for (int piece: array) {
System.out.println(piece);
}

TimeStamp on Custom X-Labels with an array of 1 value

I have this issue with the xlabels in aChartEngine when there is one value in an ArrayList. I generate my own XLabels for a line chart, but when there is one data array value, i get an unwanted TimeStamp on top of my generated XLabels.
my Code:
private XYMultipleSeriesDataset getDemoDataset() {
Calendar cal = Calendar.getInstance();
Date date = new Date();
date_value = new String[list.size()];
value_value = new String[list.size()];
for(int k = 0; k < list.size(); k++){
date_value[k] = list.get(k).get(DATE);
value_value[k] = list.get(k).get(VALUE);
}
TimeSeries series = new TimeSeries("Line Graph");
for(int j=0; j < date_value.length; j++) {
series.add(formatter.stringToDate(date_value[j]), Integer.parseInt());
}
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(series);
return dataset;
}
setChartSetting:
private void setChartSetting(XYMultipleSeriesRenderer renderer){
renderer.setXRoundedLabels(true);
renderer.setXTitle("DATES");
renderer.setYTitle(kpiname);
renderer.setApplyBackgroundColor(true);
renderer.setFitLegend(false);
renderer.setAxesColor(Color.DKGRAY);
renderer.setShowGrid(true);
renderer.setZoomEnabled(false);
renderer.setXLabels(0);
renderer.setYLabels(10);
renderer.setZoomEnabled(false, false);
renderer.setPanEnabled(false, false);
//String[] date_value = new String[list.size()];
//String[] value_value = new String[list.size()];
if(list.isEmpty() || list.size() == 0 || list == null ){
return;
}
if(name.equals(RECOVERED) || name.equals(CONVERSION)){
largest_size = (int)Double.parseDouble(value_value[0]);
}else{
if(!(value_value.length == 0)){
largest_size = Integer.parseInt(value_value[0]);
}else{
return;
}
}
//used to determine the maximum value for the y-axis
for(int x =0; x < value_value.length; x++){
if(Integer.parseInt(value_value[x]) > largest_size){
largest_size = Integer.parseInt(value_value[x]);
}
}
renderer.setYAxisMax((double)largest_size);
renderer.setYAxisMin(0);
int value_size = value_value.length;
int m = 0;
//int add = value_size/10;
int add = largest_size/10;
/*instance variables for setting the labels on the X-Axis based on weather the values in the array are
* more than 10 items or less*/
double d;
Long l;
Long l1;
double d1;
if(date_value.length <= 1){
int last = date_value.length;
int mod = 0;
//int add_mod = Math.round(last/10);
int add_mod = (int)Math.round((double)Math.round(last));
l = Long.valueOf(formatter.stringToDateReport(date_value[0]).getTime());
d = l.doubleValue();
/*tried this to see if i can remove the timestamp*/
//renderer.addXTextLabel(0.0, "");
//renderer.removeXTextLabel(0.0);
//renderer.clearXTextLabels();
renderer.addXTextLabel(d, date_value[0]);
}
else if(date_value.length < 10){
for(int i = 0; i < date_value.length; i++){
if(i >= date_value.length){
break;
}
l = Long.valueOf(formatter.stringToDateReport(date_value[i]).getTime());
d = l.doubleValue();
renderer.addXTextLabel(d, date_value[i]);
}
} else if(date_value.length >= 10){
int last = date_value.length;
//int last = 28;
//Log.d(TAG, "last is " + last);
int mod = 0;
//int add_mod = Math.round(last/10);
int add_mod = (int)Math.round((double)Math.round(last) /10); // do this to get the decimal value with a double and then round to get nearset whole with int
for(int i =0; i < date_value.length; i++){
if(mod >= date_value.length){
break;
}
l1 = Long.valueOf(formatter.stringToDateReport(date_value[mod]).getTime());
d1 = l1.doubleValue();
renderer.addXTextLabel(d1, date_value[mod]);
mod+=add_mod;
}
}
}
}
and then:
chartView = ChartFactory.getLineChartView(context, getDemoDataset(), setChartSettings(renderer));
When there are multiple values, it plots the graph well with my custom XLabels(format is MMM-yyyy), but when there is only one value in the ArrayList, it generates thats time stamp.
here is an image:
This was a bug, indeed. You can download a version including a fix for it feature here.

Images based on Array Values

I have a dice game and I am trying to change the image of the Die that is selected after the dice are rolled to a "Dead Die" image. I have tried everything I can think of and I always end up finding the Value "0" in the Index or something else but never the correct Die.
When the dice is selected it sets it's value to a Negative Number. Example I select 6 it changes the value to -6 and changes the die to the -6 die image
How can I get it to display AND KEEP the "DEAD" image I want.
Here is the area where it gets the Images
//Get the Dice Images
public Integer getImage(int index) {
if (diceValues[index] == 0) {
return letterImages.get(index);
} else {
return diceImages.get((diceValues[index]));
}
}
I have tried changing
return letterImages.get(index);
to every possible combination of everything and when I do get it to change the image it always ends up at "0" or the the current number of dice selected or the some other number that I'm just not sure how it came up with.
Here is the entire DieManager class
package com.mygames.dice;
import java.util.HashMap;
import android.util.Log;
public class DieManager {
// Will return the Indexes of the dice when this is used
public static final int INDEX_FLAG = 1;
// Will return the values of the dice when this is used
public static final int VALUE_FLAG = 2;
// Will return the absolute values of the dice when this is used
public static final int ABS_VALUE_FLAG = 3;
// The array that holds the dice
private int[] diceValues = { 0, 0, 0, 0, 0, 0 };
private HashMap<Integer, Integer> diceImages = new HashMap<Integer, Integer>();
private HashMap<Integer, Integer> deadImages = new HashMap<Integer, Integer>();
private HashMap<Integer, Integer> letterImages = new HashMap<Integer, Integer>();
// Sets #newValue to dieValues[#index]
public void setValue(int index, int newValue) {
Log.w(getClass().getName(), "Index = " + index + " Value = " + newValue);
diceValues[index] = newValue;
}
public DieManager() {
super();
initializeMaps();
}
private void initializeMaps() {
diceImages.put(-6, R.drawable.die6_select);
diceImages.put(-5, R.drawable.die5_select);
diceImages.put(-4, R.drawable.die4_select);
diceImages.put(-3, R.drawable.die3_select);
diceImages.put(-2, R.drawable.die2_select);
diceImages.put(-1, R.drawable.die1_select);
diceImages.put(1, R.drawable.die1_roll);
diceImages.put(2, R.drawable.die2_roll);
diceImages.put(3, R.drawable.die3_roll);
diceImages.put(4, R.drawable.die4_roll);
diceImages.put(5, R.drawable.die5_roll);
diceImages.put(6, R.drawable.die6_roll);
deadImages.put(-1, R.drawable.die1_dead);
deadImages.put(-2, R.drawable.die2_dead);
deadImages.put(-3, R.drawable.die3_dead);
deadImages.put(-4, R.drawable.die4_dead);
deadImages.put(-5, R.drawable.die5_dead);
deadImages.put(-6, R.drawable.die6_dead);
letterImages.put(0, R.drawable.die_no);
letterImages.put(1, R.drawable.die_no);
letterImages.put(2, R.drawable.die_no);
letterImages.put(3, R.drawable.die_no);
letterImages.put(4, R.drawable.die_no);
letterImages.put(5, R.drawable.die_no);
}
public void rollDice() {
boolean isNewRound = (numOnTable() == 0);
for (int j = 0; j < 6; j++) {
// If its a new round then the dice value can be changed from 0.
// Else it can't
if (isNewRound || diceValues[j] != 0)
diceValues[j] = (int) ((Math.random() * 6) + 1);
}
}
// Returns the value or absolute value
public int getValue(int index, int flag) {
if (flag == ABS_VALUE_FLAG)
return Math.abs(diceValues[index]);
return diceValues[index];
}
// If a dice value is 0 then its a letter
public int numOnTable() {
int count = 6;
for (int i : diceValues) {
if (i == 0)
count--;
}
return count;
}
// Picking up makes the dice value 0
public void pickUp(int[] highlighted) {
for (int i = 0; i < highlighted.length; i++)
diceValues[highlighted[i]] = 0;
}
// A negative value means a die is highlighted
public void toggleHighlight(int index) {
diceValues[index] *= -1;
}
public void clearTable() {
diceValues[0] = 0;
diceValues[1] = 0;
diceValues[2] = 0;
diceValues[3] = 0;
diceValues[4] = 0;
diceValues[5] = 0;
}
// Return the dice that aren't 0
public int[] diceOnTable(int flag) {
if (flag == ABS_VALUE_FLAG) {
int[] array = new int[diceValues.length];
for (int i = 0; i < diceValues.length; i++)
array[i] = Math.abs(diceValues[i]);
return array;
}
return diceValues;
}
//Returns dice that are negative
public int[] getHighlighted(int flag) {
int[] dirtyArray = { 0, 0, 0, 0, 0, 0 };
int count = 0;
for (int j = 0; j < 6; j++) {
if (diceValues[j] < 0) {
if (flag == INDEX_FLAG)
dirtyArray[count++] = j;
if (flag == VALUE_FLAG)
dirtyArray[count++] = diceValues[j];
if (flag == ABS_VALUE_FLAG)
dirtyArray[count++] = Math.abs(diceValues[j]);
}
}
int[] cleanArray = new int[count];
//Returns an array of length 0
if (count == 0)
return cleanArray;
System.arraycopy(dirtyArray, 0, cleanArray, 0, count);
return cleanArray;
}
// Finds in dieValues same #value and excludes #index
public int[] findPairs(int index, int flag) {
int[] dirtyArray = { 0, 0, 0, 0, 0, 0 };
int count = 0;
for (int j = 0; j < 6; j++) {
if (j != index
&& Math.abs(diceValues[j]) == Math.abs(diceValues[index])) {
if (flag == INDEX_FLAG)
dirtyArray[count++] = j;
if (flag == VALUE_FLAG)
dirtyArray[count++] = diceValues[j];
if (flag == ABS_VALUE_FLAG)
dirtyArray[count++] = Math.abs(diceValues[j]);
}
}
int[] cleanArray = new int[count];
if (count == 0)
return cleanArray;
System.arraycopy(dirtyArray, 0, cleanArray, 0, count);
return cleanArray;
}
//Get the Dice Images
public Integer getImage(int index) {
if (diceValues[index] == 0) {
return letterImages.get(index);
} else {
return diceImages.get((diceValues[index]));
}
}
//Get the Number of dice remaining that are not 0
public int numDiceRemain() {
int counter = 0;
for (int j = 0; j < diceValues.length; j++) {
if (diceValues[j] > 0)
counter++;
}
return counter;
}
}
The dice value can never be zero on a roll because of the following line in your rollDice() method:
diceValues[j] = (int) ((Math.random() * 6) + 1);
And this seems logical to me. Why would the value on a die ever be zero?

Android Renderscript String Functions?

Are there any string functions in Renderscript? Like vsprintf, for example?
Specifically, I'd like to convert a float to a string. Do I have to write that from scratch?
Thanks!
Sorry, here's a better one. It'll work for integers as well but they have ".000" added on.
char stringBuffer[50];
static const int MAX_STRING_LENGTH = sizeof(stringBuffer) - 1;
void drawFloat(float value, int x, int y) {
int index = 0;
int scaledValue = (int)(value * 1000);
index = MAX_STRING_LENGTH;
stringBuffer[index] = 0;
while(scaledValue > 0 || index > MAX_STRING_LENGTH - 4) {
index--;
if(index == MAX_STRING_LENGTH - 4) {
stringBuffer[index--] = '.';
}
int digitValue = scaledValue % 10;
stringBuffer[index] = '0' + digitValue;
scaledValue /= 10;
}
if(value < 0) {
stringBuffer[index--] = '-';
}
rsgDrawText(&stringBuffer[index], x - 10, y + 5);
}
Couldn't find a simple way so...
void drawInteger(int value, int x, int y) {
char text[50] = "0";
int index = 0;
if(value != 0) {
index = 49;
text[index] = 0;
while(value > 0) {
index--;
int digitValue = value % 10;
text[index] = '0' + digitValue;
value /= 10;
}
if(value < 0) {
text[index--] = '-';
}
}
rsgDrawText(&text[index], x - 10, y + 5);
}
void drawFloat(float value, int x, int y) {
char text[50] = "0.000";
int index = 0;
if(value != 0) {
int integerPart = (int)(value * 1000);
index = 49;
text[index] = 0;
while(integerPart > 0) {
index--;
if(index == 45) {
text[index--] = '.';
}
int digitValue = integerPart % 10;
text[index] = '0' + digitValue;
integerPart /= 10;
}
if(value < 0) {
text[index--] = '-';
}
}
rsgDrawText(&text[index], x - 10, y + 5);
}

Algorithm help needed - rows/columns in a grid

I have been killing myself trying to develop an algorithm to determine the positions of the cells in a grid by which row or column they are in.
For example, I have an 8x8 grid and I need to determine all of the positions of the cells in row 3.
The issue that I have is that, without alot of loops, I need to figure out a way to map the position clicked to the row and column that contain that cell.
Here is what I did to create an ArrayList of the cells:
public class GameBoard {
public ArrayList<Row> rows = new ArrayList<Row>();
public ArrayList<Column> columns = new ArrayList<Column>();
private int maxPositions;
public GameBoard(int rowCount, int colCount) {
this.maxPositions = (rowCount * colCount) - 1;
for(int x = 0;x < rowCount;x++){
Row row = new Row(x);
row.cells.addAll(this.getRowCells(x, colCount));
rows.add(row);
}
for(int x = 0;x < colCount;x++){
Column column = new Column(x);
column.cells.addAll(getColumnCells(x, colCount));
columns.add(column);
}
}
private ArrayList<Cell> getRowCells(int rowId, int colCount) {
ArrayList<Cell> row_cells = new ArrayList<Cell>();
int first_position = ((rowId * colCount) -1);
Cell cell = new Cell();
cell.id = first_position;
row_cells.add(cell);
int x = 1;
while(x < colCount) {
cell = new Cell();
cell.id = first_position + x;
row_cells.add(cell);
x++;
}
return row_cells;
}
private ArrayList<Cell> getColumnCells(int columnId, int rowCount) {
ArrayList<Cell> col_cells = new ArrayList<Cell>();
int first_position = columnId;
Cell cell = new Cell();
cell.id = first_position;
col_cells.add(cell);
int x = 1;
while(x < rowCount) {
cell = new Cell();
cell.id = rows.get(x).cells.get(columnId).id;
col_cells.add(cell);
x++;
}
return col_cells;
}
public Cell getColumnNextCell(int position, int columnId) {
Cell cell = null;
if ((position > -1) && (position <= maxPositions)) {
cell = columns.get(columnId).cells.get(position + 1);
}
return cell;
}
public Cell getColumnPreviousCell(int position, int columnId) {
Cell cell = null;
if ((position > 0) && (position <= maxPositions)) {
cell = columns.get(columnId).cells.get(position - 1);
}
return cell;
}
public Cell getRowNextCell(int position, int rowId) {
Cell cell = null;
if ((position > -1) && (position <= maxPositions)) {
cell = rows.get(rowId).cells.get(position + 1);
}
return cell;
}
public Cell getRowPreviousCell(int position, int rowId) {
Cell cell = null;
if ((position > 0) && (position <= maxPositions)) {
cell = rows.get(rowId).cells.get(position - 1);
}
return cell;
}
}
As you can see with the methods like getColumnNextCell() through getRowPreviousCell() the logic is a mess and I am stuck on how to determine the column and row of the clicked cell (as I explained). Any help would be greatly appreciated.
For clarification the Row and Column objects are identical. They look like this.
public class Column {
public int id;
public ArrayList<Cell> cells = new ArrayList<Cell>();
public Column(int idx) {
this.id = idx;
}
}
Can't you just use an array for the cells
int rows, cols;
Cell[][] cells;
public GameBoard(int rowCount, int colCount) {
this.maxPositions = (rowCount * colCount) - 1;
this.rows = rowCount;
this.cols = colCount;
this.cells = new Cell[rows];
for(int i=0; i < rows; i++) {
cells[i] = new Cell[cols];
for(int j = 0; j < cols; j++) {
cells[i][j] = new Cell();
// whatever else you need to do...
}
}
}
This way it would be easy to get the cell you want
Cell getCell(int position) {
return cells[position/rows][position%cols];
}
Why don't you use simple two dimensional array? If your grid is not resized after creation, there is no advantage of using ArrayList objects. So what about having your base class something like this:
public class GameBoard {
private Cell[][] cells;
private int maxPositions;
private int rows;
private int cols;
public GameBoard(int rowCount, int colCount) {
this.rows = rowCount;
this.cols = colCount;
cells = new Cell[rowCount][colCount];
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < colCount; j++) {
cells[i][j] = new Cell();
}
}
this.maxPositions = (rowCount * colCount) - 1;
}
...
}
Now you don't have row and column objects, just array of cells. Isn't those cells actually what you need or do those row and column arrays have another purpose? So I think you are trying to do simple thing with too difficult way.

Categories

Resources