How to print all the ways to cut off a string - combination - algorithm

input: "abcd"
output: a list of all the ways to cut off the string.
[ ["a", "bcd"],["a", "b", "cd"], ["a", "b", "c", "d"],
["ab", "cd"], ["ab", "c", "d"],
["abc", "d"],
["abcd", ""]
]
I want a recursive solution. Preferably Java but not need to be language specific.
Thank you!
Please notice "abd" "c" is not valid, because you cannot rearrange the order.

There are a lot of ways to solve this problem. Here is one of them
import java.util.ArrayList;
import java.util.List;
public class Splitter {
public static void main(String[] args) {
final String string = "abcd";
//You should add empty string as a base
printAllSplits(string, 0, new ArrayList<>(List.of(new StringBuilder())));
}
static void printAllSplits(String s, int currentIndex, List<StringBuilder> list) {
if (currentIndex == s.length()) { //reached the end, nothing left to split
System.out.println(list);
return;
}
//We should consider two decisions at each index: 1. split
// 2. don't split
//split here
if (currentIndex > 0) {
list.add(new StringBuilder(Character.toString(s.charAt(currentIndex))));
printAllSplits(s, currentIndex + 1, list);
//remove it not to affect a future call
list.remove(list.size() - 1);
}
//don't split here
list.get(list.size() - 1).append(s.charAt(currentIndex));
printAllSplits(s, currentIndex + 1, list);
}
}
You can modify this code to fit your needs. If you don't like or understand anything, feel free to ask. Also, if you need exactly a string, you can convert string builder to string at the end. I use string builder, because it's mutable.

Related

How can i use greedy algorithm to allocate products to stores

I got assigned to solve this problem: Given number of products sold in specific stores, is there a way to find from which stores to buy all products with the condition of buying only one product from each store.
For example if you have stores A,B,C and products a,b,c with each shop selling:
A: a,c
B: a,b,c
C: c
Answer: You will be buying products a from store A product b from store B and product c from store C.
From this am assuming you cant have more products than stores since you are buying just 1 product from each store and you want to buy all of them.
My thought was using a greedy algorithm where you first buy products exclusively sold in one store and solving this hierarchically but it doesn't always work
You could solve it by finding the max-flow on a maximum cardinality matching in a bipartite graph. Construct a source s going to all the stores, {A, B, C}, and draw a directed edge to each product that store has, {a, b, c}. Then the products to the sink, t. Label all edges with 0/1.
Then apply the greedy Ford–Fulkerson method. If the max-flow reaches the number of stores and the number of products, then one has a viable solution. This will complete in at most O((number of stores, products)✖️(number of edges)), since the maximum capacity is the number of stores and products, and each iteration increases the capacity.
it took me a while but i created some c# with my approach to the problem:
class BuyFromShops
{
private static Dictionary<string, List<string>> _shops = new()
{
{ "A", new List<string> { "a", "b" } },
{ "B", new List<string> { "a", "b", "c" } },
{ "C", new List<string> { "c" } }
};
static void Main(string[] args)
{
// the items that have been bought
var itemsBought = new List<string>();
// sort items by how often they are sold
List<string> itemsToBuy = GetDistinctItemsSortedByCountAscending();
// sort shops by amount of items
List<string> shopsToBuyFrom = GetShopSortedByItemCountDescending();
// for shop from most items to least
foreach (var shop in shopsToBuyFrom)
{
// for items from rarest to most common
foreach (var item in itemsToBuy)
{
// if item is in shop remove item and go to next store
string baughtItem = string.Empty;
if (_shops[shop].Contains(item) && !itemsBought.Contains(item))
{
_shops[shop].Remove(item);
itemsBought.Add(item);
baughtItem = item;
Console.WriteLine($"Bought {item} from {shop}.");
}
if (baughtItem == string.Empty) continue;
itemsToBuy.Remove(baughtItem);
break;
}
}
Console.WriteLine("Remaining items in shops.");
foreach (var shop in _shops)
{
Console.WriteLine($"{shop.Key}: {string.Join(", ", shop.Value)}");
}
Console.WriteLine($"Items bought: {string.Join(", ", itemsBought)}");
}
private static List<string> GetShopSortedByItemCountDescending()
{
var result = from entry in _shops orderby entry.Value.Count descending select entry.Key;
return result.ToList();
}
private static void BuyItem(string store, string item)
{
_shops[store].Remove(item);
}
private static List<string> GetDistinctItemsSortedByCountAscending()
{
var distinctItems = new Dictionary<string, int>();
foreach (string item in _shops.SelectMany(shop => shop.Value))
{
if (!distinctItems.ContainsKey(item))
{
distinctItems.Add(item, 1);
}
else
{
distinctItems[item] += 1;
}
}
var distinctItemsSorted = from entry in distinctItems orderby entry.Value select entry.Key;
return distinctItemsSorted.ToList();
}
}
My Python code, prints the solution:
stores = ['A', 'B', 'C']
products = ['a', 'b', 'c']
# Initialize the product inventory in each store
# A: a,c
# B: a,b,c
# C: c
inventory = {
'A': ['a', 'c'],
'B': ['a', 'b', 'c'],
'C': ['c']
}
# Greedy algorithm to allocate products to stores
allocated_products = {}
for product in products:
allocated_products[product] = None
for store in stores:
for product in inventory[store]:
if allocated_products[product] == None:
allocated_products[product] = store
break
# Print the solution
for product, store in allocated_products.items():
print(f'Product: {product}, Store: {store}')

How to create a set in Ballerina?

I have a requirement to create a set of strings using an array of strings in Ballerina. Other than using reduce() or checking indexOf() before inserting, I couldn't find a way to create a set using Ballerina programming language.
string[] arr = ["a", "b", "c", "a", "d", "c"];
string[] set = arr.reduce(function(string[] accum, string item) returns string[] {
if accum.indexOf(item) == () {
accum.push(item);
}
return accum;
}, []);
Is there a better way to create a set in Ballerina?
Since what you want is just set of strings, I would suggest to use a map.
import ballerina/io;
public function main() {
string[] s = ["a", "b", "a"];
map<()> m = {};
foreach var i in s {
m[i] = ();
}
string[] unique = m.keys();
io:println(unique);
}
For set of complex type, we can go with a table and do something similar to what we did with map.
If the intended members of the set are not strings; we can use a table instead. Below is an example
import ballerina/io;
type TblConstraint record {|
//can use a type that is a subtype of anydata
readonly anydata keyValue;
|};
public function main() {
int[] arr = [1, 2, 3, 3, 4, 4, 5];
table<TblConstraint> key(keyValue) setImpl = table [];
foreach int item in arr {
if (!setImpl.hasKey(item)) {
setImpl.put({keyValue: item});
}
}
//unique values as in a set
io:println(setImpl.keys());
}

How do I group by sequence in LINQ?

Given sequence :
["1","A","B","C","2","F","K","L","5","6","P","I","E"]
The numbers represent items that I identify as headers, whereas the letters represent items that I identify as data. I want to associate them into groups like this.
1:A,B,C
2:F,K,L
5:
6:P,I,E
I can easily achieve this using a foreach or while loop on the enumerator, but is there a LINQ'ish way to achieve this? This is a recurring pattern in my domain.
Here's a solution with LINQ. It's a little bit complicated though. There may be room for some tricks. It doesn't look that terrible but it can be more readable with a foreach loop.
int lastHeaderIndex = default(int);
Dictionary<string, IEnumerable<string>> groupedItems =
items.Select((text, index) =>
{
int number;
if (int.TryParse(text, out number))
{
lastHeaderIndex = index;
}
return new { HeaderIndex = lastHeaderIndex, Value = text };
})
.GroupBy(item => item.HeaderIndex)
.ToDictionary(item => item.FirstOrDefault().Value,
item => item.Skip(1).Select(arg => arg.Value));
You can make use of a fold:
var aggr = new List<Tuple<Int,List<String>>>();
var res = sequence.Aggregate(aggr, (d, x) => {
int i;
if (Int32.TryParse(x, out i)) {
var newDict = d.Add(new Tuple(i, new List<string>()));
return newDict;
}
else {
var newDict = d[d.Count - 1].Item2.Add(x);
return newDict;
}
}).ToDictionary(x => x.Item1, x => x.Item2);
However, this doesn't look so nice, since there's lacking support for immutable values. Also, I couldn't test this right now.
foreach loop with int.TryParse should help. 'GroupBy' from LINQ won't help here much.
Since this a common pattern in your domain, consider streaming the results instead of gathering them all into a large in-memory object.
public static IEnumerable<IList<string>> SplitOnToken(IEnumerable<string> input, Func<string,bool> isSplitToken)
{
var set = new List<string>();
foreach(var item in input)
{
if (isSplitToken(item) && set.Any())
{
yield return set;
set = new List<string>();
}
set.Add(item);
}
if (set.Any())
{
yield return set;
}
}
Sample usage:
var sequence = new[] { "1", "A", "B", "C", "2", "F", "K", "L", "5", "6", "P", "I", "E" };
var groups = SplitOnToken(sequence, x => Char.IsDigit(x[0]));
foreach (var #group in groups)
{
Console.WriteLine("{0}: {1}", #group[0], String.Join(" ", #group.Skip(1).ToArray()));
}
output:
1: A B C
2: F K L
5:
6: P I E
Here's what I ended up using. Pretty much the same structure as phg's answer.
Basically, it is an aggregate function that maintains a Tuple containing:
1: the accummulated data.
2: state of the parser.
The aggregating function does an if-else to check if currently examined item is a group header or a regular item. Based on this, it updates the datastore (last part of the tuple) and/or changes the parser state (first part of the tuple).
In my case, the parser state is the currently active list (that upcoming items shall be inserted into).
var sequence = new[]{ "1","A","B","C","2","F","K","L","5","6","P","I","E"};
var aggr = Tuple.Create(new List<string>(), new Dictionary<int,List<string>>());
var res = sequence.Aggregate(aggr, (d, x) => {
int i;
if (Int32.TryParse(x, out i))
{
var newList = new List<string>();
d.Item2.Add(i,newList);
return Tuple.Create(newList,d.Item2);
} else
{
d.Item1.Add(x);
return d;
}
},d=>d.Item2);

Predicate builder contains

I am trying to execute query through MVC3 with predicate builder. I am getting the error
"Unable to cast the type 'System.Boolean' to type 'System.Object'. LINQ to Entities only supports casting Entity Data Model primitive types."
I have query passed as below
if (!string.IsNullOrEmpty(SearchObj.EmployeeIDSortId.ToString()) && SearchObj.EmployeeIDSortId > 0)
{
string[] vals =new string[' '];
if (SearchObj.EmployeeIDSortId == 1)
{
vals = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k","l" };
}
else if (SearchObj.EmployeeIDSortId == 2)
{
vals = new string[] { "m", "n", "o", "p", "q", "r", "s" };
}
else if (SearchObj.EmployeeIDSortId == 3)
{
vals = new string[] { "t", "u", "v", "w", "x", "y", "z" };
}
employeepredicate =
employeepredicate.And(emp => emp.EmployeeName.Substring(0, 1).ToLower().Equals(vals.Any()));
}
Can you please suggest what is wrong with this ,I guess it is only due to my query vals.Any().
Thanks
Let me preface - I'm unfamiliar with the And method, but the .Equals(vals.Any()) doesn't look right to me. So, I assume that And takes a function returning a bool. What you're really looking for is to find out if the first character in the employee name is contained in the vals array:
employeepredicate = employeepredicate.And(
emp => vals.Contains(emp.EmployeeName.Substring(0, 1).ToLower()));

LINQ Partition List into Lists of 8 members [duplicate]

This question already has answers here:
Split List into Sublists with LINQ
(34 answers)
Closed 10 years ago.
How would one take a List (using LINQ) and break it into a List of Lists partitioning the original list on every 8th entry?
I imagine something like this would involve Skip and/or Take, but I'm still pretty new to LINQ.
Edit: Using C# / .Net 3.5
Edit2: This question is phrased differently than the other "duplicate" question. Although the problems are similar, the answers in this question are superior: Both the "accepted" answer is very solid (with the yield statement) as well as Jon Skeet's suggestion to use MoreLinq (which is not recommended in the "other" question.) Sometimes duplicates are good in that they force a re-examination of a problem.
Use the following extension method to break the input into subsets
public static class IEnumerableExtensions
{
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
List<T> toReturn = new List<T>(max);
foreach(var item in source)
{
toReturn.Add(item);
if (toReturn.Count == max)
{
yield return toReturn;
toReturn = new List<T>(max);
}
}
if (toReturn.Any())
{
yield return toReturn;
}
}
}
We have just such a method in MoreLINQ as the Batch method:
// As IEnumerable<IEnumerable<T>>
var items = list.Batch(8);
or
// As IEnumerable<List<T>>
var items = list.Batch(8, seq => seq.ToList());
You're better off using a library like MoreLinq, but if you really had to do this using "plain LINQ", you can use GroupBy:
var sequence = new[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
var result = sequence.Select((x, i) => new {Group = i/8, Value = x})
.GroupBy(item => item.Group, g => g.Value)
.Select(g => g.Where(x => true));
// result is: { {1,2,3,4,5,6,7,8}, {9,10,11,12,13,14,15,16} }
Basically, we use the version of Select() that provides an index for the value being consumed, we divide the index by 8 to identify which group each value belongs to. Then we group the sequence by this grouping key. The last Select just reduces the IGrouping<> down to an IEnumerable<IEnumerable<T>> (and isn't strictly necessary since IGrouping is an IEnumerable).
It's easy enough to turn this into a reusable method by factoring our the constant 8 in the example, and replacing it with a specified parameter.
It's not necessarily the most elegant solution, and it is not longer a lazy, streaming solution ... but it does work.
You could also write your own extension method using iterator blocks (yield return) which could give you better performance and use less memory than GroupBy. This is what the Batch() method of MoreLinq does IIRC.
It's not at all what the original Linq designers had in mind, but check out this misuse of GroupBy:
public static IEnumerable<IEnumerable<T>> BatchBy<T>(this IEnumerable<T> items, int batchSize)
{
var count = 0;
return items.GroupBy(x => (count++ / batchSize)).ToList();
}
[TestMethod]
public void BatchBy_breaks_a_list_into_chunks()
{
var values = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var batches = values.BatchBy(3);
batches.Count().ShouldEqual(4);
batches.First().Count().ShouldEqual(3);
batches.Last().Count().ShouldEqual(1);
}
I think it wins the "golf" prize for this question. The ToList is very important since you want to make sure the grouping has actually been performed before you try doing anything with the output. If you remove the ToList, you will get some weird side effects.
Take won't be very efficient, because it doesn't remove the entries taken.
why not use a simple loop:
public IEnumerable<IList<T>> Partition<T>(this/* <-- see extension methods*/ IEnumerable<T> src,int num)
{
IEnumerator<T> enu=src.getEnumerator();
while(true)
{
List<T> result=new List<T>(num);
for(int i=0;i<num;i++)
{
if(!enu.MoveNext())
{
if(i>0)yield return result;
yield break;
}
result.Add(enu.Current);
}
yield return result;
}
}
from b in Enumerable.Range(0,8) select items.Where((x,i) => (i % 8) == b);
The simplest solution is given by Mel:
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
int i = 0;
return items.GroupBy(x => i++ / partitionSize).ToArray();
}
Concise but slower. The above method splits an IEnumerable into chunks of desired fixed size with total number of chunks being unimportant. To split an IEnumerable into N number of chunks of equal sizes or close to equal sizes, you could do:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items,
int numOfParts)
{
int i = 0;
return items.GroupBy(x => i++ % numOfParts);
}
To speed up things, a straightforward approach would do:
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items,
int partitionSize)
{
if (partitionSize <= 0)
throw new ArgumentOutOfRangeException("partitionSize");
int innerListCounter = 0;
int numberOfPackets = 0;
foreach (var item in items)
{
innerListCounter++;
if (innerListCounter == partitionSize)
{
yield return items.Skip(numberOfPackets * partitionSize).Take(partitionSize);
innerListCounter = 0;
numberOfPackets++;
}
}
if (innerListCounter > 0)
yield return items.Skip(numberOfPackets * partitionSize);
}
This is faster than anything currently on planet now :) The equivalent methods for a Split operation here

Resources