如何随机化单词中的字母


55

根据一个有争议的故事,对于拉德尼格来说,杂乱无章的杂物对拉德尼格的影响不大,就像伊诺格像原始杂物杂乱无章的拳头一样。

因此,为了好玩,将单词中的字母顺序随机化而又将第一个和最后一个字母保留在原位的最短函数是什么?

这是我使用JavaScript的目的。删除的所有空格都为124130个字符。

function r(w) {
  var l=w.length-1;
  return l<3?w:w[0]+w.slice(1,l).split("").sort(function(){return Math.random()-.5}).join("")+w[l];
}

总是欢迎使用较短的JavaScript。


  • 编辑:添加了长度检查。简短的功能不应失败。

3
Haskell,4个字符:r=id
Thomas Eding

2
是。它返回与输入完全相同的东西。另一方面,我们如何处理标点符号?我们是否只对仅由字母组成的单词进行运算?
Thomas Eding

1
@trinithis不确定您在说什么,但是id是身份功能。我仍然希望用不到100个字符来查看Haskell解决此问题的方法。
阿伦

3
是否应更新规范以要求结果的均匀分布?这将不允许使用4个字符的Haskell解决方案。这也将不允许您的示例Javascript解决方案(通过执行类似的排序是不统一的)。
Thomas Eding

2
+1为第一句话:实际上我花了几秒钟才意识到它被
拼错

Answers:


21

Haskell,4个字符

trinithis提出的功能实际上符合规范:

s=id

它返回的字符串不变,因此将第一个和最后一个字符保留在原处,并对所有其他字符进行排列

如果某人对排列的概率分布不满意,则可以使用一种解决方案来获得更好的分布。显然要复杂得多:

哈斯克尔, 110 120 107个字符

import Random
s l=randomRIO(1,length l-2)>>=g.($l).splitAt
g(a:b,c:d)=fmap(a:).s$c:b++d
g(a,b)=return$a++b

使用此功能的程序示例:

main = getLine >>= s >>= putStrLn

18
“对排列的概率分布不满意”使我发笑。:)
Tomalak

@Rotsor如何调用该函数?
阿伦

我在帖子中添加了一个示例。
Rotsor 2011年

fmap((a:t!!i:).tail)
2011年

3
应该删除第一个解决方案,因为它不符合挑战标准。挑战说明说“随机化”。根据meta,random不能总是具有相同的输出
mbomb007 '16


15

Ruby,44个字符

r=->w{w[h=1..-2]=[*w[h].chars].shuffle*"";w}

也适用于短单词,即带有一个,两个或三个字符的单词原样返回。

编辑:使用Ventero的数组散点图的想法保存另一个字符。


实际上是44个字符。最终,我通过微调自己的答案,得出了完全相同的答案-现在,读完您的书后,我感觉就像是模仿者。
Aleksi Yrttiaho 2011年

@ user2316当然你是对的。谢谢。
霍华德

11

Ruby 1.9,46个字符

r=->w{w[0]+[*w[1..-2].chars].shuffle*""+w[-1]}

+1这种使用array-splat的方法也为我节省了一个字符。好想法。
霍华德

我不知道ruby-在ruby1.8上它失败了,所以我想我需要一个never版本吗?它适用于“ I”之类的输入吗?
用户未知

@user:在那里说“ Ruby 1.9”。;)-Ventero-我忘记提及的明智要求之一是,它对于字长0和1不应失败。
Tomalak

11

高尔夫脚本

作为“功能”(命名为代码块):20个字符

{1/(\)\{;9rand}$\}:r

当操作堆栈中最顶层的元素时:16个字符

1/(\)\{;9rand}$\

这不是一个很好的改组,但对于此任务来说可能还可以。(也就是说,它会“看够乱”。)不过,在两个字符的成本,你可以得到很多通过更换更好的洗牌99.?
Ilmari Karonen

对于单字母单词,此操作将失败,并且我也不认为应该允许该函数返回字符串,字符串数组,字符串(而不是单个字符串)。
Martin Ender 2015年

11

C ++,79个字符带有范围检查

string f(string s){if(s.size()>3)random_shuffle(&s[1],&s.end()[-1]);return s;}

C ++, 8165个字符不进行范围检查

string f(string s){random_shuffle(&s[1],&s.end()[-1]);return s;}

使用按引用传递而不是返回结果可从任一解决方案中省去另外10个字符。

完整的程序,读取一串单词并重新组合它们:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <ctime>
#include <string>

using namespace std;    
string f(string s){if(s.size()>3)random_shuffle(&s[1],&s.end()[-1]);return s;}

int main() {
    std::srand(std::time(0));
    std::string s;
    while(std::cin >> s)
        std::cout << f(s) << " ";
    std::cout << std::endl;
}

士气:不要建立已经存在的东西。 哦,溢出检查很麻烦。


好的,std::random_shuffle这对我来说是新的。顺便说一句,我认为您忘记#include<string>了完整的代码。
Scott Logan

1
我最初的想法就是这样。不幸的是,没有内置的功能可以在JS中就地对字符串进行改组。
Tomalak

对于非常短的字符串失败。
用户未知

没错,您错过了长度检查(我也这样做了)。BTW @Arlen的答案也值得一看。
Tomalak

1
@userunknown这就是我的意思,“溢出检查是针对失败的”。公平地说,几乎所有其他解决方案也是如此。
康拉德·鲁道夫

8

Python,86个字符

import random as r
def f(w):t=list(w[1:-1]);r.shuffle(t);return w[0]+''.join(t)+w[-1]

这是一个使用它的示例:

for x in ["ashley", "awesome", "apples"]:
    print f(x)

这是我的第一个高尔夫练习代码。解决问题后,我决定查看答案,这并不奇怪,我的答案并非唯一。虽然这很有趣:o)

在查看其他响应后,我确实做了一个更改,并且正在更改我的import语句以使用别名。好想法。; o)


但是,您的解决方案获得了我的投票!:p
2011年

短弦失败;如果在短字符串()上失败,我的python答案将为75个字符from random import*\nf=lambda w:w[0]+''.join(sample(w[1:-1]),len(w)-2)+w[-1]
jimbob博士2012年

7

C(K&R)-88 86 87个字符

r(char*s){int m,j,l=strlen(s)-2,i=l;while(--i>0){j=rand()%l+1;m=s[j];s[j]=s[1];s[1]=m;}}

C中没有内置的交换或随机播放功能,因此我必须手动进行:(

Ungolfed r()的示例程序:

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

// -----------------------------------------------------------------------
r( char *s )
{
    int m, j, l=strlen(s)-2, i=l;

    while (--i>0)
    {
        j = rand() % l + 1;

        m = s[j];
        s[j] = s[1];
        s[1] = m;
    }

}
// -----------------------------------------------------------------------
int main()
{
    char s[] = "anticipated";

    srand( time(0) );
    r( s );
    puts( s );

    return 0;
}

编辑:修复了s少于3个字符时的错误(感谢用户意识到这一点!)


1
在glibc中,有一个(不是?)非标准库函数strfry
机械蜗牛

有趣的经历,如果我愿意接受的话char s[] = "na"; // not anticipated
用户未知,

@user uknown:我刚刚编辑了代码并修复了它,感谢您注意到该错误!(我只是在while循环的条件下添加了> 0,“又花了我两个”,但需要添加字符:))
Harry K.11年

1
@机械蜗牛:我认为strfy仍然在glibc中。
哈里K.11年

7

python,87 79 75 93 92字符(处理长度为0.1的字符串)

from random import*
f=lambda w:w if 4>len(w)else w[0]+''.join(sample(w[1:-1],len(w)-2))+w[-1]

编辑:最初认为它应该拆分字符串(它以128个字符进行;现在以87个字符做为要求)。啊,我的阅读能力很差。

编辑2:从def更改为lambda函数,从def保存6个字符。假设样本已经导入到名称空间(from random import sample)中,则可以将其降低到60左右。

编辑3:每个小工具的建议都是“ len(w [1:-1])”(12个字符)到“ len(w)-2”(8个字符)。

编辑4:JBernando保存了一个字符(已考虑from random import *并认为它是等效的-无需意识到其中的空间import *是不必要的)。未知用户添加了19个字符w if len(w)<4 else以正确处理0和1个字符字符串。

编辑5:每个亭子的代码高尔夫技巧保存了另一个字符。 if len(w)<4 elseif 4>len(w)else


但是,问题仅将输入定义为一个单词,而不是字符串。:)
本·理查兹

1
@ sidran32:谢谢,我不好。我刚刚注意到(在重读时),然后看到了您的评论;删除-编辑-并取消删除。
jimbob博士2011年

想法-您可以通过这样做来修剪3个字符。...def f(w):j = w [1:-1]; return w [0] +''。join(r.sample(j,len(j)))+ w [-1]
arrdem 2011年

@rmckenzie:好主意。但是,在将您的评论修剪为lambda函数(节省6个字符)之后,就在我看到您的评论之前,因此我无法再使用您的方法来定义中间变量。
jimbob博士2011年

3
len(w)-2代替len(w[1:-1])
gnibbler 2011年

6

C ++,111个 97个字符

std::string f(std::string s){for(int i=s.size()-1;i>1;std::swap(s[rand()%i+1],s[--i]));return s;}

这是一个完整的程序,供那些希望对其进行测试的人使用:

#include<string>
#include<iostream>

std::string f(std::string s){for(int i=s.size()-1;i>1;std::swap(s[rand()%i+1],s[--i]));return s;}

int main(){
    for(int i = 0; i<100; ++i)
    std::cout<<f("letters")<<std::endl;
}

编辑

意识到无需将两个交换索引都随机化,保存一个变量和几个其他字符。


优秀的。大多数解决方案在输入非常少时就会失败。不是你的
用户未知,

6

php(68个字符)

$r=preg_replace('/^(\w)(\w+)(\w)$/e','$1.str_shuffle($2).$3',trim($w));

较短(60个字符)

$r=preg_replace('/(.)(.+)(.)/e','$1.str_shuffle($2).$3',$w);

+1非常好。:)实际上,您可以删除trim(),并在正则表达式中可以删除锚点并使用.代替\w
Tomalak

@Tomalak建议我尝试在Perl中重写此解决方案。包括他的建议在内,我得到了:use List::Util 'shuffle';sub r{$_[0]=~m/(.)(.+)(.)/;$1.join('',shuffle split//,$2).$3;}这是87个字符。如果没有使用行,则为62个字符
本·理查兹

您可以提供此工作的演示吗?因为我做不到...
Steve Robbins

6

Perl- 96(或71)个字符 84(或59)个字符

这就是我在Perl中想到的。通过几种不同的方法来完成此操作,但这似乎比我到目前为止想象的要短,只有97个字符。

use List::Util 'shuffle';sub r{($b,@w)=split//,$_[0];$e=pop(@w);return$b.join('',shuffle@w).$e;}

但是,如果您剪切出“ use”行(我想这是有效的,因为其他人在其C程序中排除了#include行),我可以将其进一步缩减为71个字符

sub r{($b,@w)=split//,$_[0];$e=pop(@w);return$b.join('',shuffle@w).$e;}

编辑 建议我尝试执行@tobius'方法。这样,我将其减少到84个字符,或者删除了59个字符使用行:

use List::Util 'shuffle';sub r{$_[0]=~m/(.)(.+)(.)/;$1.join'',shuffle split//,$2.$3}

2
将您的版本缩短至87:use List::Util 'shuffle';sub r{($b,@w)=split//,$_[0];$e=pop@w;join'',$b,(shuffle@w),$e}
mbx 2011年

1
@ sidran32您可以实现Perl @tobius答案的变体,只是为了进行比较吗?
Tomalak

@Tomalak当然,我会尝试一下。
本·理查兹

1
将您的正则表达式版本缩短了3个字符:use List::Util 'shuffle';sub r{$_[0]=~m/(.)(.+)(.)/;$1.join'',shuffle split//,$2.$3}
mbx 2011年

真好 为了清楚起见,我也习惯于使用括号的堆积帮助。打高尔夫球时的坏习惯。:P
本·理查兹

5

Ruby,77个 75个字符

def r(s);f=s.size-2;1.upto(f){|i|x=rand(f)+1;t=s[i];s[i]=s[x];s[x]=t};s;end

我的Scala解决方案使用的语言略为冗长。无论如何我都不是Ruby专家,所以可能还有改进的余地。


哇。与“ I”一起使用,作为您的scala解决方案。
用户未知,

5

红宝石1.9,77 48 46 44个字符

r=->w{w[h=1..-2]=[*w[h].chars].shuffle*"";w}

免责声明:我根据排名最高的答案进行了调整-后来发现完全相同的答案。您可以查看我仍然忠实于最初想法的历史,但对于短的lambdas和shuffle

如果允许空词,则为56 54个字符

r=->w{w.empty?||w[h=1..-2]=[*w[h].chars].shuffle*"";w}

没有人期望西班牙语为“ I”。
用户未知

尝试处理0或1个字母的案件
Aleksi Yrttiaho 2011年

5

Python 3,94 93 91个字符

使用不同的技术。可能在Python 2中也可以使用。

from random import*
s=lambda x:x[0]+''.join(sample(x[1:-1],len(x)-2))+x[-1]if x[0:-1]else x

如果长度为1 ,则... if x[0:-1] else x给出x(否则将被复制)。因此,该函数适用于长度为0和1的字符串。

sample()https://stackoverflow.com/questions/2668312/shuffle-string-in-python/2668366#2668366

由于它是一种表达,我们可以使用一个lambda(消除returndef和一对括号)。

编辑: from random import*在其他Python提交之后,保存1个字符。


知道我在这里这么晚了,但是可以x[0:-1]成为x[:-1]
扎卡里

4

JavaScript- 118122个字符

较短的JavaScript-118个字符,没有空格。使用与OP大致相同的算法,但链接较少。我尝试了很多递归,并尝试了一些迭代,但是它们都倾向于以某种方式陷入困境。

function s(w)
{
    w = w.split('');
    var a = w.shift(),
        z = w.pop();
    return z?a + (w.sort(function() { return Math.random() - .5}).join('')) + z:a;
}

不通过“ I”测试。
用户未知,

@Ryan return z?a+...+z:w;用作隐式长度检查将是有序的。无声的假设是该函数将仅接收“有效”字词。
Tomalak

好点的,除了w通过了修改,所以我必须使用aelse三元的。已编辑,最多122个字符。
Ryan Kinal

@Ryan:我相信a输入两个字母是错误的。:-\该死的,下一次我将更加仔细地列出要求。
Tomalak

我认为实际上不会。z仅当单词是一个字母(或更少)时才是未定义的。
Ryan Kinal

4

D,62个字符

import std.random;void s(char[] s){randomShuffle(s[1..$-1]);}

好吧,我用普通的char数组而不是真实的字符串作弊(这是不可变的char [],所以没有就地改组)

使用长度检查进行编辑,还需要14个时间

import std.random;void s(char[] s){if(s.length>1)randomShuffle(s[1..$-1]);}

对于“ I”这样的输入,它返回什么?
用户未知,

返回结果将更公平(=更好的可比性)。
康拉德·鲁道夫

@user范围错误。@ konrad,这将需要return s;and char []返回11个更多的字符
棘轮怪胎

@ratchet您能发布整个程序吗?顺便说一句,我不明白你为什么要计数import std.random;,而不仅仅是函数。
阿伦

我猜想您可以通过省略char[] s(使其成为char[]s)中的空格来节省1个字节,但是多年以来我都没有使用D。
蒂姆·恰斯(TimČas)2016年

4

PHP 5.3(60个字符)

$r=!$w[2]?:$w[0].str_shuffle(substr($w,1,-1)).substr($w,-1);

改进到56个字符,不再需要版本5.3:

$r=substr_replace($w,str_shuffle(substr($w,1,-1)),1,-1);

+1是其他PHP答案的不错选择。不短,但没有正则表达式是一个加号。
Tomalak

更新了较短的解决方案,不需要版本5.3
migimaru,2011年

旧版本不正确:返回true短字符串。
泰特斯(Titus)2016年

3

Perl-111个字符(不使用任何库函数)

sub r{($f,@w)=split//,shift;$l=pop@w;while(@w){if(rand(9)>1){push@w,shift@w}else{push@t,pop@w}}join'',$f,@t,$l}

用法

$in="randomizethis";
$out = &r($in);
print "\nout: $out";
sub r{($f,@w)=split//,shift;$l=pop@w;while(@w){if(rand(9)>1){push@w,shift@w}else{push@t,pop@w}}join'',$f,@t,$l}

3

蟒蛇

这是python 的90 89112个字符!

编辑1:这次作为功能!

(感谢g子手)

编辑2:现在可以处理简短的单词

(感谢用户未知)

import random as r
def q(s):
 a=list(s)
 b=a[1:-1]
 r.shuffle(b)
 if len(s)<4:
  return s
 return a[0]+''.join(b)+a[-1]

如果您遵循规范并编写函数,甚至更少:)
gnibbler

啊,可怜的洗牌不能用在弦上
gnibbler 2011年

1
随机模块就像我在一家夜总会一样……我们俩都只是在适当地洗牌!:)
Andbdrew 2011年

不适用于“ I”之类的输入;返回“ II”。
用户未知,

谢谢!它现在可以处理简短的单词,但会稍长一些:)
Andbdrew

3

Scala中,135个139 142 156字符

def r(s:String)={var(x,o,t,f)=(0,s.toArray,' ',s.size-2)
for(i<-1 to f){t=o(i)
x=util.Random.nextInt(f)+1
o(i)=o(x)
o(x)=t}
o.mkString}

-7:删除':String'(可以推断返回类型)
-7:删除'return'(最后一个表达式是返回值)
-3:分解s.size-2
-4:toCharArray->toArray


无需花哨的Python字符即可与“ I”和“Verwürfel”一起使用。:)但是,我使用'shuffle'的解决方案要短一些。
用户未知,

@user unknown感谢您的编辑:-)
Gareth

3

Python,86个字符

Slnicig是安全的,所以没有任何人可以嘲笑。所有leghtns上的Wkros。

from random import*
def f(x):x=list(x);t=x[1:-1];shuffle(t);x[1:-1]=t;return''.join(x)

3

C ++ 11:-68 66个字符

auto f=[&](){if(s.size()>2)random_shuffle(s.begin()+1,s.end()-1);};

完整程序:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[]){

  string s = "SomestrinG";
  auto f=[&](){if(s.size()>2)random_shuffle(s.begin()+1,s.end()-1);};

  f();
  cout << s << endl;
  return 0;
}

输入字符串中的硬编码合法吗?
Thomas Eding

@trinithis我以为我们只关心函数本身。该程序仅显示如何使用该功能。无论如何,在这种情况下,不对输入进行硬编码不会有所作为;只需添加string s; cin >> s;
阿伦

3

Ruby 1.9,43个字符

r = w [0] + [* w [1 ..- 2] .chars] .shuffle.join + w [-1]

不适用于1个字符长的字符串(与该字符重复),并且对于空字符串失败。



3

R,104(126)

f=function(w){s=strsplit(w,"")[[1]];paste(c(s[1],sample(s[2:(length(s)-1)]),s[length(s)]),collapse="")}

用法:

for (i in 1:10) print(f("parola"))
[1] "plraoa"
[1] "prolaa"
[1] "praola"
[1] "parloa"
[1] "plaora"
[1] "palroa"
[1] "porlaa"
[1] "ploraa"
[1] "porlaa"
[1] "ploraa"

以下功能适用于长度小于3的单词:

f=function(w){s=strsplit(w,"")[[1]];ifelse(length(s)<3,w,paste(c(s[1],sample(s[2:(length(s)-1)]),s[length(s)]),collapse=""))}

f("pl")
[1] "pl"
f("a")
[1] "a"

部分任务是不移动首字母和尾字母。
Tomalak 2012年

@Tomalak固定!
Paolo 2012年

它可以处理长度小于3的单词吗?
Tomalak 2012年

@Tomalak现在应该可以了!感谢您的更正!
Paolo 2012年

3

Python,102个字符

def f(x):t=list(x)[1:-1];k='';exec'k+=t.pop(id(7)%len(t));'*len(t);return[x[0],x[0]+k+x[-1]][len(x)>1]

没有进口!适用于1个字符及以上的单词。这是我的第一个高尔夫入门,并且受到BlueEyedBeast从Shortest代码开始的启发,它为使用id(Object)的想法产生了不确定的输出


说明:它使输入中的字母组成一个列表,但不包括第一个和最后一个,并反复从该列表中弹出并追加到新的字母,直到为空。它从中弹出的索引是id(7)%len(我们从中弹出的列表)。由于id(7)是对象7的内存地址,因此本质上是随机的。因此,现在我们有了一个来自原始输入中心的随机加扰字母的列表。现在要做的就是相应地附加原始输出的首字母和尾字母,我们得到了我们想要的输出:(首字母)+(加扰的中间字母)+(最后字母)。


3

R, 95 92 91个字符

f=function(w,a=el(strsplit(w,'')),b=length(a))cat(a[1],sample(a[c(1,b)],b-2),a[b],sep="")

利用R的惰性求值来计算a和b作为函数参数,从而节省空间并在以后重复使用。也不同于其他R答案,这适用于所有长度大于1个字符的单词。下面的例子:

> f("hippopotamus")
hpuoopaitmps

> f("dog")
dog

> f("az")
az

编辑: 替换unlist()[[]] 用el()替换了[[1]]


2

D:55个字符

void f(T)(T s){if(s.length>2)randomShuffle(s[1..$-1]);};

完整程序:

import std.stdio, std.random, std.conv;

void f(T)(T s){if(s.length>2)randomShuffle(s[1..$-1]);};

void main(){

  char[] s = to!(char[])("SomestrinG");

  f(s);
  writeln(s);
}

我认为else s零件丢失了吗?
Tomalak

1
@Tomalak不,不是,因为没有必要。如果字符串的长度小于或等于2,则我们将其保留下来。另外,randomShuffle()就位。
阿伦

哇,D很有竞争力。我认为randomShuffle(s[1..$-1])可以s[1..$-1].randomShuffleIIRC(除非是在d版本低于这个帖子)
扎卡里

2

Erlang,188172132 字符

f([H|C=[_|_]])->T=[lists:last(C)],[H|s(C--T,T)];f(X)->X. s([],N)->N;s(D,N)->E=[lists:nth(random:uniform(length(D)),D)],s(D--E,E++N).

我仍在学习Erlang,因此希望使它简短一些。

完整代码(string_shuffle模块):

-module(string_shuffle).
-export([f/1]).

f([H|C=[_|_]])->
    T=[lists:last(C)],
    [H|s(C--T,T)];f(X)->X.
f(X)->X.

s([],N)->N;
s(D,N)->
    E=[lists:nth(random:uniform(length(D)),D)],
    s(D--E,E++N).

编辑

将改组部分作为单独的功能使用,不再需要列表的头和尾传递。

编辑2

进行了重组,以删除其中一种f功能模式,将shuffle函数更改lists:delete为仅接受两个参数,更改为--[],将lists:reverse调用交换为lists:last

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.