Shuffle list to maximise distances between similar elements - shuffle

In a list of URLs
http://a.com/foo
http://b.com/bar
http://a.com/monkey
http://c.com/prune
http://a.com/bear
http://b.com/walrus
http://b.com/baz
http://b.com/plugh
I want to maximise the distance between any pair of a.com's, any pair of b.com's etc. This needs to be cheap but does not have to be optimum. (I am using a list of URLs to download files from websites a.com, b.com, c.com, and do not wish to visit any particular site with a higher frequency than necessary. In the example here, we would hit the b.com site 3 times in succession, which should be avoided.)
I would ideally like a Java library but would settle for pseudocode.
Maximise sum of pairwise distances in array seems to be a similar problem but didn't have a simple answer - I simply want something that's "good enough"

Since no answers, I wrote my own. It's very crude but works. It reads a list of URLs, extracts the hosts, counts them and then fills a pigeon-hole array with indexes proportional to the inverse frequency of the hosts.
package org.xmlcml.cmine.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
public class URLShuffler {
public static final Logger LOG = Logger.getLogger(URLShuffler.class);
static {
LOG.setLevel(Level.DEBUG);
}
// in case we needed extra pigeonholes but it doesn't seem to for medium problems
private static int TOL = 1;
private List<String> urls;
private Multiset<String> domains;
private Map<String, Integer> currentIndexByDomain;
private Map<String, Integer> countByDomain;
private List<String> outputUrls;
public URLShuffler() {
}
public void readURLs(List<String> urls) {
this.urls= urls;
domains = HashMultiset.create();
for (String url : urls) {
String domain = getDomain(url);
domains.add(domain);
}
LOG.debug(domains);
}
// this would be better using java.net.URL
private String getDomain(String url) {
int idx = url.indexOf("//");
if (idx != -1) {
url = url.substring(idx+2);
}
idx = url.indexOf("/");
String domain = url.substring(0, idx);
return domain;
}
public List<String> getShuffledUrls() {
currentIndexByDomain = new HashMap<String, Integer>();
countByDomain = new HashMap<String, Integer>();
outputUrls = new ArrayList<String>();
for (int i = 0; i < urls.size() * TOL; i++) {
outputUrls.add("");
}
// this is a convenience method wrapping Guava sort.
for (Multiset.Entry<String> entry : CMineUtil.getEntriesSortedByCount(domains)) {
LOG.debug(entry);
countByDomain.put(entry.getElement(), entry.getCount());
currentIndexByDomain.put(entry.getElement(), entry.getCount() - 1);
}
for (String url : urls) {
String domain = getDomain(url);
Integer currentIndex = currentIndexByDomain.get(domain);
Integer count = countByDomain.get(domain);
int slot = (urls.size() * currentIndex * TOL) / count;
currentIndexByDomain.put(domain, currentIndex - 1);
addUrl(url, slot);
}
return outputUrls;
}
private void addUrl(String url, int slot) {
boolean filled = fillLower(url, slot);
if (!filled) {
fillUpper(url, slot);
}
}
// if slot is not free run upwards till next free slot
private boolean fillUpper(String url, int slot) {
for (int i = slot; i < outputUrls.size(); i++) {
if (fill(url, i)) {
return true;
}
}
return false;
}
// if slot is not free run downwards till next free slot
private boolean fillLower(String url, int slot) {
for (int i = slot; i >= 0; i--) {
if (fill(url, i)) {
return true;
}
}
return false;
}
private boolean fill(String url, int slot) {
if (outputUrls.get(slot).equals("")) {
outputUrls.set(slot, url);
return true;
}
return false;
}
}
```

Related

Radix sort with array of custom linked lists - error trying to print

I have an assignment for class and we have to use a radix sort using an array of linked lists.
It should split a string into a key and value, and store them as an Entry.
public class Entry {
public String key;
public String value;
public Entry() {
}
public Entry(String key, String value) {
this.key = key;
this.value = value;
}
}
The Entry class is pretty basic, I dont think it has any problems.
The issue is that I can either get the while loop to iterate exactly once and then the program completely stops, or I can cause an infinite loop depending on whether or not I use array[10].removeHead() twice or not
import java.io.File; // Import the File class
import java.io.FileNotFoundException; // Import this class to handle errors
import java.util.Scanner; // Import the Scanner class to read text files
public class RadixSort {
public static void main(String[] args) {
try {
LinkedList[] array = new LinkedList[11];
for(int i = 0; i < 11; i++) {
array[i] = new LinkedList();
}
File myObj = new File("years.txt");
Scanner myReader = new Scanner(myObj);
int counter = Integer.parseInt(myReader.nextLine());
System.out.println(counter);
while (myReader.hasNextLine()) {
String string = myReader.nextLine();
if (string.equals("END")) break;
String[] parts = string.split(",");
String part1 = parts[0];
String part2 = parts[1];
Entry a = new Entry(part1, part2);
array[10].addTail(a);
//System.out.println(array[ 0].removeHead().key);
// this works, but gives null ptr exception^^^
System.out.println(array[10].peekHead().key + "," + array[10].peekHead().value);
array[10].removeHead();
}
for (int i = counter; i > 0; i--) {
while (!array[10].peekHead().key.contains(null)) {
String s = array[10].peekHead().key;
String g = array[10].peekHead().value;
int a = Integer.parseInt(s.substring(i-1));
System.out.println(a);
//System.out.println(s);
Entry bruh = new Entry(s, g);
array[a].addHead(bruh);
if (s.equals(null)) System.out.println("error");
//System.out.println(array[10].peekHead().key);
//System.out.println(array[a].peekHead().value);
array[10].removeHead();
System.out.println(array[a].peekHead().key);
}
for (int j = 0; j < 10; j++) {
while (!array[j].peekHead().key.equals(null)) {
array[10].addTail(array[j].removeHead());
}
}
}
while (!array[10].peekHead().key.equals(null)) {
System.out.println(array[10].peekHead().key + "," + array[10].peekHead().value);
array[10].removeHead();
}
myReader.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
When I try to print it out it just prints the first Node a bunch of times and then throws a NullPointerException like below:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.CharSequence.toString()" because "s" is null
at java.base/java.lang.String.contains(String.java:2054)
at RadixSort.main(RadixSort.java:34)
My linked list class should work fine, I did it for our first assignment and tested it pretty thoroughly and it had no errors that I could see.
I tried to just add a couple more removeHead() functions to see if that would change anything and it just keeps throwing that dumb null pointer exception. If anyone could help with anything I would be incredibly grateful.

Solr's labelled relationship indexation performance

I want to move from anonymous relationships (childDocuments) to labelled.
During testing, performance degradation was detected when integrating documents into Solr on identical schemas and documents.
Solr (8.1.1) configuration (local, 1 node, default settings): solr -e cloud
Test: start integration of 500 documents several times and calculate the average integration time.
Labelled relationship example:
{
"id": "parent_xxx",
"items": [{"id": "child_xxx"}]
}
Anonymous relationship example:
{
"id": "parent_xxx",
"_childDocuments_": [{"id": "child_xxx"}]
}
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.common.SolrInputDocument;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Scratch {
private static final int DOC_COUNT = 500;
private static final int ITERATION_COUNT = 5;
private static final boolean ANONYMOUS_CHILDREN = true;
private static final boolean LABELED_CHILDREN = false;
public static void main(String[] args) throws IOException, SolrServerException {
long anonymousTime = 0;
long labelledTime = 0;
for (int i = 0; i < ITERATION_COUNT; i++) {
List<SolrInputDocument> anonymousDocs = createSolrDocuments(ANONYMOUS_CHILDREN);
cleanSolrCollection();
anonymousTime += writeToSolr(anonymousDocs);
List<SolrInputDocument> labeledDocs = createSolrDocuments(LABELED_CHILDREN);
cleanSolrCollection();
labelledTime += writeToSolr(labeledDocs);
}
System.out.println("Avg anonymous time: " + (anonymousTime / ITERATION_COUNT));
System.out.println("Avg labelled time: " + (labelledTime / ITERATION_COUNT));
}
private static List<SolrInputDocument> createSolrDocuments(boolean isAnonymous) {
List<SolrInputDocument> request = new ArrayList<>();
for (int i = 0; i < DOC_COUNT; i++) {
SolrInputDocument parent = new SolrInputDocument();
parent.setField("id", "parent_" + i);
SolrInputDocument child = new SolrInputDocument();
child.setField("id", "child_" + i);
if (isAnonymous) {
parent.addChildDocument(child);
} else {
parent.addField("items", child);
}
request.add(parent);
}
return request;
}
private static void cleanSolrCollection() throws IOException, SolrServerException {
try (SolrClient client = getSolrClient()) {
client.deleteByQuery("main", "*:*");
}
}
private static long writeToSolr(List<SolrInputDocument> documents) throws IOException, SolrServerException {
long startAt = System.currentTimeMillis();
try (SolrClient client = getSolrClient()) {
client.add("main", documents);
}
return System.currentTimeMillis() - startAt;
}
private static SolrClient getSolrClient() {
return new HttpSolrClient.Builder("http://localhost:8983/solr")
.allowCompression(true)
.build();
}
}
Results:
500 docs with anonymous relationship ~ 29ms
500 docs with labelled relationship ~ 981ms
Is it normal behavior for Solr when working with named relationships?
I have not been able to find any information about that.
The performance difference of 20-30 times does look strange.

How to design multipane with 3 fragment using Android-PanesLibrary?

Good Day Developers,
I already implement this fantastic library called "Android-PanesLibrary" by Kenrick Rilee. and what i want to achive is something like this.
But i end up doing like this :
my first problem if in showDetails method i delete the comment symbol, it will showing up an error. but if i make the method empty, it will run just like the second image.
my objective is how can this be done just using string array data?
Any ideas or help would be greatly appreciated.
Environment : Windows 7, Android Studio, Genymotion.
This is MainMenuFragment.java :
public class MainMenuFragment extends android.app.ListFragment {
private static int sExampleNum = 0;
protected final String TAG = "mainmenuFragment" ;
#ViewById(R.id.menu_listview)
protected ListView menuListView ;
private View parentView;
int mCurCheckPosition = 0;
public MainMenuFragment() {
super();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Resources res = getResources();
String [] mainmenulistview = res.getStringArray(R.array.listview_main_menu);
ArrayAdapter<String> connectArrayToListView = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_activated_1,mainmenulistview);
setListAdapter(connectArrayToListView);
if (savedInstanceState != null) {
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
showDetails(mCurCheckPosition);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
showDetails(position);
}
// if I un-comment on method bellow, it will result an error.
void showDetails(int index) {
//mCurCheckPosition = index;
//getListView().setItemChecked(index, true);
//PCDesktopFragment_ pcDesktop = (PCDesktopFragment_) getFragmentManager().findFragmentById(R.id.sub_one_fragment);
//if (pcDesktop == null || pcDesktop.getShownIndex() != index) {
// welder_pipe_reg = PCDesktopFragment_.newInstance(index);
// android.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
// ft.replace(R.id.sub_one_fragment, pcDesktop);
// ft.commit();
//}
}
}
and then i already create a class called PCDesktopFragment.java that extends ListFragment (this should be showing up on second fragment using listfragment)
#EFragment(R.layout.sub_one_menu)
public class PCDesktopFragment_ extends ListFragment {
View v;
public static int i;
public static PCDesktopFragment_ newInstance(int index){
PCDesktopFragment_ f = new PCDesktopFragment_();
Bundle args = new Bundle();
args.putInt("index", index);
index = i;
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
inflater.inflate(R.layout.sub_one_menu, container, false);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (i == 0) {
String [] sub_a = {"Test1","Test2"};
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, sub_a));
}
}
//#ItemClick(R.id.sub_one_listview)
//protected void handleDomainClick(int position) {
// Fragment f = null ;
// if (position == 0) {
// f = new PCDesktopFragment_();
// }
// Activity a = getActivity();
// if (f != null && a != null && a instanceof FragmentLauncher)
// ((FragmentLauncher) a).addFragment(this, f);
//}
}

How to make a deep copy of lucene TokenStream object

I am trying to create a custom solr filter which will keep only the token that has maximum integer value. In doing so, I have written the following code so far:
public final class MaxValueTokenFilter extends TokenFilter {
private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);
public MaxValueTokenFilter(TokenStream in) {
super(in);
}
#Override
public boolean incrementToken() throws IOException {
TokenStream clonedTokenStream = DeepCopy???(input);
int maxVal = 0;
//increamenting the clonedTokenStream should not increment the actual tokenStream
while (clonedToken.incrementToken()) {
final String term = termAttribute.toString();
int currentNumber = Integer.parseInt(term);
if(currentNumber > maxVal)
{
maxVal = currentNumber;
}
}
//increment the actual token to match the maximum value
while (input.incrementToken()) {
final String term = termAttribute.toString();
int currentNumber = Integer.parseInt(term);
if(currentNumber == maxVal)
{
return true;
}
}
return false;
}
#Override
public void reset() throws IOException {
super.reset();
}
}
Can somebody help me to make the DeepCopy of the TokenStream object so that incrementing the copied TokenStream does not increment the actual TokenStream.

objects follow the same class

I have a problem, I am working on a larger project, and I made a small project to test this problem.
The problem being:
I have made a button which spawns enemy's. When an enemy hits allyCopy it bounces back in the opposite direction. But the problem is that EVERY instance of enemy bounces back when a single one hits the test object.
My code:
my main class:
package {
import flash.display.*;
import flash.ui.*;
import flash.events.*;
public class MainClass extends MovieClip {
public var speed:int = 3;
public static var enemyArray:Array = [];
public var randNumber:Number = 0;
public static var allyCopy1 = new allyCopy();
public function MainClass() {
stage.addEventListener(Event.ENTER_FRAME, update);
spawnButton1.addEventListener(MouseEvent.CLICK, spawnEnemy);
allyCopy1.addEventListener(MouseEvent.MOUSE_DOWN, dragOn, true);
allyCopy1.addEventListener(MouseEvent.MOUSE_UP, dragOff, true);
addChild(allyCopy1);
allyCopy1.x = 60,25;
allyCopy1.y = 208,05;
}
public function update(e:Event)
{
/*for (var i:Number = 0; i < enemyArray.length; i++)
{
enemyArray[i].x -= speed;
}*/
}
public function dragOn (e:MouseEvent)
{
allyCopy1.startDrag();
trace("drag");
}
public function dragOff (e:MouseEvent)
{
allyCopy1.stopDrag();
}
public function spawnEnemy(e:MouseEvent)
{
randNumber = Math.random();
trace(randNumber);
var enemy1 = new enemy ();
addChild(enemy1);
enemyArray.push(enemy1);
if (randNumber <= .5)
{
enemy1.x = 526.25;
enemy1.y = 68.05;
} else
{
enemy1.x = 526.25;
enemy1.y = 200.05;
}
}
}
}
The enemy class:
package {
import flash.display.*;
import flash.events.*;
public class enemy extends MovieClip {
public static var hp:int = 100;
public static var speed = 3;
public function enemy() {
addEventListener(MouseEvent.CLICK, killEnemy);
addEventListener(Event.ENTER_FRAME, update);
}
public function update (e:Event) {
x -= speed;
if ( x <= 0)
{
MainClass.enemyArray.pop();
trace(MainClass.enemyArray);
}
if(MainClass.allyCopy1.hitTestObject(this))
{
speed = -3;
}
}
public function killEnemy (e:MouseEvent)
{
this.parent.removeChild(this);
trace(MainClass.enemyArray);
MainClass.enemyArray.pop();
}
}
}
Well the problem is that speed is static variable. This means that it's not separate for each enemy, but it's common (shared) for all instances. So if you change it, it changes everywhere..
Don't do variables static that often - it's pretty bad practice. The very same thing will happen with life - if you decrease the life of one enemy, it will decrease the life of all enemies (all instances of that class).

Resources